C语言实现贪吃蛇

article/2025/10/25 21:57:58

C语言实现贪吃蛇

贪吃蛇项目是在b站的一位老师那里边学边敲的(现在视频被老师删掉了),在这里记录一下代码和学习时的一些思考,希望自己以后能用链表将贪吃蛇实现。

思考过程:

贪吃蛇 C语言实现
1.打印首页 --FirstPage()功能:提示用户按下空格开始游戏。;知识点:C语言中接受直接接受键盘的一个字符而不用按回车就开始执行下一步命令的函数:_getch(),在conio.ht头文件中。
2.清空屏幕 --TestSpace()功能:用户按下空格以后清空首页。知识点:利用system("cls")实现。
3.打印游戏界面 --ShowBackground()功能:打印一个行为20,宽为20的一个游戏区域。知识点:把游戏区域的小方块和空格存在一个g_strGameBack二维数组里面,每次需要打印游戏界面的时候,就打印一次g_strGameBack数组。
4.刷新游戏界面 --Sleep()功能:蛇的每次状态改变,为了在视觉上产生变化,都需要我们去打印一次游戏界面,即打印一次变化后的g_strGameBack数组。知识点:使用Sleep()函数和system("cls")实现屏幕的刷新,Sleep()函数可以使程序在此等待一段时间后执行,单位是毫秒,该函数包含在windows.h头文件中。
5.将生成的蛇画到背景中 DrawSnake()功能:根据蛇的坐标,将蛇显示在背景中。知识点:用g_arrsnake[SNAKE_LONG][3]数组来保存蛇的坐标,然后使打印背景的数组g_strGameBack,这个数组上面的对应坐标打印出小方块。打印出的小方块就是蛇。
6.设置蛇的开始位置 SetSnakeRandPos()功能:游戏开始时,生成蛇的随机坐标,蛇的默认长度是3个小方块。知识点:设置随机数种子,然后分别生成横坐标和纵坐标的随机值。使用srand((unsigned)time(NULL))来设置随机数种子,然后rand生成随机数。相关函数在time.h头文件中。生成的横坐标就是小方块的横坐标,生成的纵坐标得乘上2,因为小方块占用2个字节。然后把坐标值保存在g_arrsnake数组中,然后调用DrawSnake()函数,把蛇画到背景中。
7.删除蛇 --DestroySnake()功能:从背景中删掉上一个状态的蛇。知识点:连续循环3次,把方块拷贝到空白地图上面
8.蛇动起来 --SnakeMove()功能:让蛇朝着某一个方向移动, 其实是删除蛇原来蛇原来的位置以后,将蛇的上个格子的值,赋给当前的值。然后再将蛇头转移到下一个方向上,并判断,如果蛇头与方格重合到,那么就表示蛇已经死亡,这个时候应该结束程序。知识点:遍历g_arrsnake数组的所有行下标,如果下标不为0,就表示这是上一次蛇所在位置,那么这一次我们可以将前一个结点的值赋给当前结点,这个时候,除蛇头以外的所有点坐标都已经更新,然后再处理蛇头,而蛇头的方向是有可能改变的,这个时候可以事先设立一个全局数组g_nSnakeDir,来表示蛇头每次的方向。通过g_nSnakeDir改变蛇头的方向以后,利用循环判断蛇会不会咬到自己。
9.蛇改变方向 --ChangeDir()功能:用户从键盘输入蛇的前进方向,根据用户输入的值改变前进方向。知识点:该步骤得用GetAsyncKeystate()异步检测函数,不能用_getch()函数,该函数会等待用户输入,如果不输入则蛇不移动(同步检测),比如:GetAsyncKeyState('W'); 表示如果输入W,就返回一个非0值。
10.判断蛇是否死亡 --SnakeDie()功能:判断蛇是否会撞墙,在SnakeMove()函数中,蛇头改变方向以后,我们可以根据蛇头的坐标和蛇身体的坐标来判断蛇会不会咬到自己,现在我们要来判断蛇会不会撞墙。知识点:我们可以判断蛇头的坐标这个位置是不是小方格来判断蛇有没有撞墙。所以这个函数专门用于新的背景被打印出来以后。
11.随机产生食物 --ProduceFood()功能:在游戏区域随机尝试一个食物,首先要判断有没有必要产生新的食物,因为如果上一次蛇没有吃到食物的话,是没有必要产生新的食物的。知识点:先利用随机数种子产生一对随机数坐标,然后要判断,如果这个随机坐标产生在蛇身所在位置,是不可以的。这里可以用while循环套住,只有产生正确而且可用的坐标才可以结束while循环。然后将最后的正确坐标打印在游戏区域,显示为食物。并将下次有必要设置食物的bool类型的值置为false12.蛇变长 --SnakeGrow()功能:蛇吃完食物以后尾结点会变长。知识点:判断蛇头坐标与食物坐标是否相等,如果相等,那么尾结点增1,注意要分四个方向来讨论,因为尾结点处于四个不同方向上,对于蛇数组的处理方式是不同的。
13.打印分数 --Score()功能:蛇每次吃食物后,在游戏区域的旁边实时的打印分数。知识点:首先确定分数所在位置的坐标,然后利用SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), rd)函数设置光标的位置,最后打印。GetStdHandle()返回标准的输入、输出或错误的设备的句柄,也就是获得输入、输出/错误的屏幕缓冲区的句柄。#然后要确定main函数中各个函数的执行顺序:FirstPage() -> TestSpace() -> system("cls") -> SetSnakeRandPos() -> while() -> {system("cls") -> ChangeDir() -> SnakeGrow() -> ProduceFood() -> SnakeMove() -> if (SnakeDie()) -> DrewSnake() -> ShowBackground() -> Score() -> Sleep()} ->system("pause") -> return 0

代码:

head.h

#define SNAKE_LONG 60
#define bool int
#define false 0
#define true 1
char g_strGameBack[20][48] = {"■■■■■■■■■■■■■■■■■■■■■■■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■                                          ■\n","■■■■■■■■■■■■■■■■■■■■■■■\n"};
//方向
enum {to_east = 2, to_west = -2, to_north = -1, to_south = 1};
//蛇数组
int g_arrsnake[SNAKE_LONG][3] = {0};  //[i][0]表示行的坐标,[i][1]表示列的坐标,[i][2]表示移动的方向
//蛇的方向
int g_nSnakeDir = to_west;
//
bool g_ProFood = true;
//产生随机坐标
int g_Row, g_Col;
//蛇长度
int g_SnakeLen = 2; 
//分数
int g_Score = 0;

main.c

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>   //_getch所在头文件
#include <time.h>
#include "head.h"
void FirstPage() {printf("\n\n\n\n\t\t\t   <<按下空格开始游戏>>\n");
}
void TestSpace() {char ch;//当输入为空格,就进入游戏while (ch = _getch()) {   //_getch的作用是读入一个字符,不用按回车if (ch == ' ') break;}
}
void ShowBackground() {for (int i = 0; i < 20; i++) {printf(g_strGameBack[i]);    //打印g_strGameBack数组20次}
}
//画蛇,根据设置好的数组将蛇画到背景中
void DrawSnake() {strncpy(&g_strGameBack[g_arrsnake[0][0]][g_arrsnake[0][1]], "□", 2);for (int i = 1; g_arrsnake[i][0] != 0; i++) {   //连续循环3次,把方块拷贝到空白地图上面strncpy(&g_strGameBack[g_arrsnake[i][0]][g_arrsnake[i][1]], "■", 2);}
}
//删除蛇残留
void DestroySnake() {for (int i = 0; g_arrsnake[i][0] != 0; i++) {   //连续循环3次,把方块拷贝到空白地图上面strncpy(&g_strGameBack[g_arrsnake[i][0]][g_arrsnake[i][1]], "  ", 2);}
}
//设置蛇的开始位置
void SetSnakeRandPos() {int nX = -1, nY = -1;srand((unsigned int)time(NULL));   //设置随机数种子nX = rand() % 19 + 1;    //因为初始长度是3,最后一列22是墙,所以第一个蛇方块上限是19nY = rand() % 18 + 1;    //因为最后一行19是墙,所以上限是18// printf("%d %d\n", nX, nY);g_arrsnake[0][0] = nY;   //行g_arrsnake[0][1] = nX * 2;g_arrsnake[0][2] = to_west;g_arrsnake[1][0] = nY;   //行g_arrsnake[1][1] = nX * 2 + 2;g_arrsnake[1][2] = to_west;g_arrsnake[2][0] = nY;   //行g_arrsnake[2][1] = nX * 2 + 4;g_arrsnake[2][2] = to_west;DrawSnake();
}
//蛇动起来
void SnakeMove() {//先从背景删掉原来的蛇DestroySnake();int i = SNAKE_LONG - 1;  //数组下标0到19for (i; i >= 1; i--) {//过滤掉非法蛇身if (g_arrsnake[i][1] == 0) continue;//把前一个结点的值,赋给当前结点g_arrsnake[i][0] = g_arrsnake[i - 1][0];g_arrsnake[i][1] = g_arrsnake[i - 1][1];g_arrsnake[i][2] = g_arrsnake[i - 1][2];}//处理蛇头g_arrsnake[0][2] = g_nSnakeDir;  //初始化方向为向西//如果是东西方向if (g_arrsnake[0][2] == to_west || g_arrsnake[0][2] == to_east) {g_arrsnake[0][1] += g_arrsnake[0][2];} else {  //如果是东西方向g_arrsnake[0][0] += g_arrsnake[0][2];}for (int j = SNAKE_LONG - 1; j >= 1; j--) {if (g_arrsnake[j][1] == 0) continue;//g_arrsnake[0][0]和g_arrsnake[0][1]为蛇头坐标//判断蛇头改变方向以后会不会咬到自己if (g_arrsnake[0][0] == g_arrsnake[j][0] && g_arrsnake[0][1] == g_arrsnake[j][1]) {printf("Snake Die!\n");printf("Ending Scores: %d\n", g_Score);system("pause");}}
}
//蛇随方向动起来
void ChangeDir() {//不可以用_getch(),该函数会等待用户输入,如果不输入则蛇不移动(同步检测)//GetAsyncKeystate()异步检测函数//GetAsyncKeyState('W'); //如果输入W,就返回一个非0值if (GetAsyncKeyState('W')) {if (g_arrsnake[0][2] != to_south) {  //不能向相反的方向走g_nSnakeDir = to_north;}} else if (GetAsyncKeyState('S')) {if (g_arrsnake[0][2] != to_north) {g_nSnakeDir = to_south;}} else if (GetAsyncKeyState('A')) {if (g_arrsnake[0][2] != to_east) {g_nSnakeDir = to_west;}} else if (GetAsyncKeyState('D')) {if (g_arrsnake[0][2] != to_west) {g_nSnakeDir = to_east;}}
}
//判断蛇是否死亡
bool SnakeDie() {//如果蛇头的下一个位置是方块,就返回0//if (g_arrsnake[0][2] == to_west || g_arrsnake[0][2] == to_east) {// if (!strncmp(&g_strGameBack[g_arrsnake[0][0]][g_arrsnake[0][1] + g_arrsnake[0][2]], "■", 2))//if (!strncmp(&g_strGameBack[g_arrsnake[0][0]][g_arrsnake[0][1]], "■", 2))//return false;//} else if (g_arrsnake[0][2] == to_north || g_arrsnake[0][2] == to_south)// if (!strncmp(&g_strGameBack[g_arrsnake[0][0] + g_arrsnake[0][2]][g_arrsnake[0][1]], "■", 2))if (!strncmp(&g_strGameBack[g_arrsnake[0][0]][g_arrsnake[0][1]], "■", 2)) {return false;}return true;
}
//随机产生新的食物
void ProduceFood() {//判断是否有必要产生新的食物if (g_ProFood == false)return;bool flag = true;srand((unsigned int)time(NULL));while (1) {g_Row = rand() % 18 + 1;g_Col = rand() % 20 + 1;//遍历蛇身,如果随机坐标产生在蛇身,就重新生成随即坐标for (int i = 0; g_arrsnake[i][0] != 0; i++)if (g_arrsnake[i][0] == g_Row && g_arrsnake[i][1] == g_Col)flag = false;if (flag == true)break;}//坐标画食物strncpy(&g_strGameBack[g_Row][g_Col * 2], "●", 2);g_ProFood = false;
}
//蛇变长
void SnakeGrow() {//如果食物坐标和蛇头坐标相等if (g_arrsnake[0][0] == g_Row && g_arrsnake[0][1] == g_Col * 2) {if (g_arrsnake[0][2] == to_east) {  //判断尾结点在哪个方向上g_arrsnake[g_SnakeLen + 1][0] = g_arrsnake[g_SnakeLen][0];g_arrsnake[g_SnakeLen + 1][1] = g_arrsnake[g_SnakeLen][1] - 2;g_arrsnake[g_SnakeLen + 1][2] = g_arrsnake[g_SnakeLen][2];} else if (g_arrsnake[0][2] == to_west) {g_arrsnake[g_SnakeLen + 1][0] = g_arrsnake[g_SnakeLen][0];g_arrsnake[g_SnakeLen + 1][1] = g_arrsnake[g_SnakeLen][1] + 2;g_arrsnake[g_SnakeLen + 1][2] = g_arrsnake[g_SnakeLen][2];} else if (g_arrsnake[0][2] == to_north) {g_arrsnake[g_SnakeLen + 1][0] = g_arrsnake[g_SnakeLen][0] + 1;g_arrsnake[g_SnakeLen + 1][1] = g_arrsnake[g_SnakeLen][1];g_arrsnake[g_SnakeLen + 1][2] = g_arrsnake[g_SnakeLen][2];} else if (g_arrsnake[0][2] == to_south){g_arrsnake[g_SnakeLen + 1][0] = g_arrsnake[g_SnakeLen][0] - 1;g_arrsnake[g_SnakeLen + 1][1] = g_arrsnake[g_SnakeLen][1];g_arrsnake[g_SnakeLen + 1][2] = g_arrsnake[g_SnakeLen][2];}g_SnakeLen++;g_ProFood = true;g_Score++;}
}
void Score() {//COORD是Windows API中定义的一种结构,表示一个字符在控制台屏幕上的坐标。COORD rd;rd.X = 56;rd.Y = 8;//设置光标位置SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), rd);//打印printf("Score: ");rd.X = 64;rd.Y = 8;//设置光标位置SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), rd);//打印printf("%d", g_Score);}
int main()
{//首页FirstPage();//按下空格TestSpace();// 清空屏幕system("cls");//设置蛇的位置SetSnakeRandPos();//打印游戏界面while (1) {system("cls");//改变方向ChangeDir();//蛇变长SnakeGrow();//产生食物ProduceFood();//蛇移动SnakeMove();//判断蛇是否死亡if (SnakeDie() == false) {printf("Snake Die!\n");printf("Ending Scores: %d\n", g_Score);break;}//在背景上显示蛇DrawSnake();//打印背景ShowBackground();//打印分数Score();Sleep(150);     //每150毫秒刷新刷新打印一次,在windows.h头文件中}system("pause");return 0;
}

游戏截图:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
*
*
*
*
*
*
其中关于SetConsoleCursorPosition()函数的知识点,我参考了:C语言如何在控制台窗口设置光标到指定位置


http://chatgpt.dhexx.cn/article/txMUjYI6.shtml

相关文章

C语言写个贪吃蛇游戏

贪吃蛇是个非常经典的游戏&#xff0c;用C语言来实现也是一个好玩的事情。这个游戏我写完后放在知乎&#xff0c;竟然点赞的人数超级多。我觉得大家喜欢&#xff0c;一个方面是因为写得简单&#xff0c;大家都能看得懂&#xff0c;一个可扩展性还是非常强的。 我试了说一下这个…

C语言实现贪吃蛇小游戏(详解)

目录 一、程序实现的原理&#xff1a; 二、预备知识 1、控制台窗口 2、通过代码将光标移动到控制台指定位置 三、 程序框架 四、具体操作 1、定义相关头文件 2、定义函数结构以及相关属性 五、完成各代码块 1、 实现将光标移到指定位置的操作 2、 打印游戏边框以及游戏初始…

小白入门——“贪吃蛇”的C语言实现(详细)

C语言实现&#xff0c;编译环境VS&#xff12;&#xff10;&#xff11;&#xff17; 附&#xff1a;easyx图形化(文章末尾&#xff09; 效果图如下 &#xff08;有一些函数kbhit&#xff0c;getch&#xff0c;在这表示为_kbhit与_getch&#xff09;//不同编译器原因 注意在Dev…

【C语言】贪吃蛇游戏的实现(一)

&#xff08;注意&#xff1a;本代码是在VC6.0环境下编译的&#xff0c;在其他环境如codeblocks下运行可能会产生意想不到的问题&#xff0c;请尽量使用VC。至于为什么要使用VC编译&#xff0c;哦&#xff0c;我亲爱的朋友&#xff0c;这只有上帝才知道&#xff09; 最近由于小…

C语言贪吃蛇 新手入门(超详细)

贪吃蛇小程序&#xff0c;主要采用C语言描述&#xff0c;采用数组进行数据存储的图形化操作界面&#xff0c;会涉及一点点C 知识&#xff08;特别少的一点点&#xff09;&#xff0c;但是有C语言基础就够用了&#xff0c;编译器&#xff1a;VS2015&#xff0c;会涉及部分库函数…

C语言实现的贪吃蛇(无EasyX,详解)

&#x1f4a6;前言 或许厌倦了枯燥的做题&#xff0c;那就学学贪吃蛇&#xff0c;激发你的学习乐趣吧~ 你将进一步加深对结构体&#xff0c;单链表&#xff0c;函数&#xff0c;循环等基础的理解。 希望对你有所帮助~ 纯C实现的贪吃蛇&#x1f40d; &#x1f4a6;前言&#x1f…

教你如何用C语言做一个简单的贪吃蛇

小时候大家可能都玩过贪吃蛇&#xff0c;但有没有想过自己做一个出来玩玩看。今天我们就教大家用C语言做一个简单的贪吃蛇游戏。这里没有采用图形界面去做&#xff0c;而是采用win32控制台。 首先&#xff0c;先把做好的游戏初始界面和游戏截图先展示一下。 游戏初始界面如图&a…

C语言实现贪吃蛇(简易)

文章目录 目录 文章目录 前言 一、游戏功能和效果 1.游戏功能 2.游戏效果 二. 游戏初步实现 1.确定地图大小 2.创建蛇对象&#xff0c;食物对象 3.初始化蛇 4.生成随机食物 5.画蛇 6.画食物 7. 游戏内移动控制 1.当按上下左右时移动方向改变 。 2.开始游戏时的默认方向 8.判…

C语言贪吃蛇小游戏,贪吃蛇C语言代码实现大全

一、C语言贪吃蛇代码实现前言 设计贪吃蛇游戏的主要目的是让大家夯实C语言基础&#xff0c;训练编程思维&#xff0c;培养解决问题的思路&#xff0c;领略多姿多彩的C语言。 贪吃蛇是非常经典的一款游戏&#xff0c;本次我们模拟在控制台实现贪吃蛇游戏&#xff0c;也就是实现…

C语言实现贪吃蛇[内附详细步骤]

C语言贪吃蛇项目 今天给分享一下使用C语言写个贪吃蛇小游戏&#xff0c;主要包含以下10部分内容&#xff1a; 1、windows光标定位与隐藏 2、欢迎界面 3、打印围墙 4、产生食物 5、初始化蛇身 6、响应按键 7、蛇身运动 8、碰撞检测 9、结束界面 10、程序运行 windows…

C语言实现贪吃蛇小游戏!(超简单详细)详细思路+源码分享

贪吃蛇&#xff08;也叫做贪食蛇&#xff09;游戏是一款休闲益智类游戏&#xff0c;有PC和手机等多平台版本。既简单又耐玩。该游戏通过控制蛇头方向吃蛋&#xff0c;从而使得蛇变得越来越长。 我们的今天的目标就是&#xff1a;用C语言来实现一个贪吃蛇项目&#xff0c;也不用…

C语言 贪吃蛇

基于C语言编写的贪吃蛇 编写环境&#xff1a;VS2019x86 这是一个基于C语言链表开发的贪吃蛇游戏 其实贪吃蛇游戏要解决的主要问题就是 1、这个游戏的基本组成元素和数据结构 2、如何初始化贪吃蛇并正常行走 3、如何判断事件发生 代码中运用到了键盘虚拟键判断、终端窗口大小的…

游戏贪吃蛇(c语言)

游戏贪吃蛇&#xff08;c语言&#xff09; 一、项目背景二、设计目的三、项目功能需求1、初始化游戏2、控制蛇的运行轨迹3、控制蛇的长度4、控制食物生成5、计算分数6、结束条件 四、系统的功能结构图五、总体设计1、初始化模块2、游戏控制模块3、运行控制模块4、食物生成模块 …

C语言实现贪吃蛇(详细版)

一、需要掌握的知识&#xff1a; C语言基础语法&#xff08;结构体、指针、链表&#xff09;、<windows.h>库、<stdlib.h>库、<time.h>库中的一些函数&#xff08;不需要额外学习&#xff0c;本文后面会讲贪吃蛇需要用到的相关函数&#xff09; 由于作者水平…

贪吃蛇(C语言实现)

文章目录 游戏说明游戏效果展示游戏代码游戏代码详解游戏框架构建隐藏光标光标跳转初始化界面颜色设置初始化蛇随机生成食物打印蛇与覆盖蛇移动蛇游戏主体逻辑函数执行按键判断得分与结束从文件读取最高分更新最高分到文件主函数 游戏说明 游戏界面当中没有打印相关的按键说明…

SDRAM控制器(初始化)

SDRAM控制器&#xff08;初始化&#xff09; 文章目录 SDRAM控制器&#xff08;初始化&#xff09;初始化模块时序逻辑图代码仿真结果 初始化模块 SDRAM 在上电之后&#xff0c;执行正常操作之前需要被初始化&#xff0c;实际上就是对上文提到的SDRAM 内部逻辑控制单元进行初始…

SDRAM 控制器设计基本完结

项目可以拓展的地方&#xff1a; 1、接口为AXI 2、接口为AXI与AXI DMA 交互 2、优化读写时序&#xff0c;使得SDRAM输出效率最大&#xff1b; 总结&#xff1a; 项目不足&#xff1a;没有进行效率的优化&#xff0c;无地址映射&#xff0c;无外接交互接口&#xff0c;功能单一…

SDRAM读写控制

SDRAM读写控制器&#xff0c;这里分为三个部分&#xff0c;分别是SDRAM的基本操作实现&#xff0c;SDRAM控制器&#xff0c;封装成FIFO,以方便使用。 一、SDRAM的基本操作&#xff1a;初始化模块、自动刷新模块、写操作模块、读操作模块、SDRAM仲裁模块&#xff0c;顶层模块。 …

SDRAM 控制器(二)——初始化模块

1、初始化模块 SDRAM 的初始化是芯片上电后必须进行的一项操作&#xff0c;只有进行了初始化操作的 SDRAM 芯片才可被正常使用。SDRAM 的初始化是一套预先定义好的流程&#xff0c;除此之外的其 他操作会导致 SDRAM 出现不可预知的后果。 初始化时序图&#xff1a; CK&#xf…

SDRAM详细介绍

概念介绍&#xff1a; SDRAM&#xff1a;Synchronous Dynamic Random Access Memory&#xff0c;同步动态随机存储器。同步是指其时钟频率和CPU前端总线的系统时钟相同&#xff0c;并且内部命令的发送与数据的传输都以它为基准&#xff1b;动态是指存储阵列需要不断的刷新来保证…