一. 相关知识介绍
1.目的
实现贪吃蛇我们用到的基本都是C语言里面所学过的知识点,既是对所学知识的熟练运用,也是复习的一种很好的方式
当然,刚开始我们也会用到一些不属于C语言的函数,我们来一起学学吧,让贪吃蛇变成我们迈出基本的C语言走向更广阔的学府的一条有意义的蛇
2. Win 32 API 介绍
Win 32 API 也就是Microsoft Windows 32位平台的应用程序编程接口
2.1 控制台程序(Console)
平常写代码运行起来的黑框其实就是控制台程序
我们可以使用cmd命令来设置控制台的大小和宽度,例如:
mode con cols=100 lines=30
当然lines和cols反着写也是可以的
大家也看到下面还有一个命令,这个呢就是修改我们控制台的标题的命令,这些命令都得在system函数的括号里面才可以实现喔!
而不要忘了任何函数使用都要包含对应的头文件,system函数的头文件就是<windows.h>!
2.2 控制台屏幕上的坐标 COORD
COORD是Windows API 中定义的一个结构体,表示一个字符在控制台屏幕缓冲区上的坐标,坐标系(0,0)的坐标在缓冲区的顶部左侧单元格,(也就是左上)
来看看COORD的声明
typedef struct _COORD
{
SHORT X,
SHORT Y,
}COORD,*PCOORD;
下面来看使用方法:
2.3GetStdHandle
GetStdHandle是一个Windows API 函数,它用于从一个特定的标准设备中取得一个句柄,使这个句柄可以操作设备
函数声明:
Handle GetStdHandle(DWORD nStdHandle);
代码段中我们先创建一个类型为Handle的变量,用来接收函数返回的句柄,有了句柄才能对该控制台进行相关的操作
2.4 GetConsoleCursorInfo
检索有关指定控制台屏幕缓冲区的光标的大小和可见性的信息
2.4.1 CONSOLE_CURSOR_INFO
typedef struct _CONSOLE_CURSOR_INFO {
DWORD dwSize;
BOOL bVisible;
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
dwSize是指光标目前的大小占比,bVisible是指光标可见性,默认true为可见,false为不可见
2.4.2 SetConsoleCursorInfo
下面是修改光标为隐形的一些操作
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//获得句柄
//影藏光标操作
CONSOLE_CURSOR_INFO CursorInfo; //找到光标相关的结构体指针
GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息
CursorInfo.bVisible = false; //隐藏控制台光标
SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态
我们首先获得本控制台的句柄,然后在找到光标的信息,用GetConsoleCursorInfo函数来找到控制台上的光标的信息,然后把成员bVisible修改为false,默认为不可见 ,这时就可以用SetConsoleCursorInfo函数来修改控制台的光标状态了
2.5 SetConsoleCursorPosition
BOOL WINAPI SetConsoleCursorPosition
{
HANDLE hConsoleOutput,
COORD pos
};
例如:
COORD pos = { 10, 5};
HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//设置标准输出上光标的位置为pos
SetConsoleCursorPosition(hOutput, pos);
这个函数的第一个参数为句柄,第二个为光标位置,修改以后我们想在控制台上的哪个地方输出字符或者其他,就可以通过修改光标位置来达到,那么这样一看,我们以后还不止一次的会用到它,那么大家应该都心知肚明了,我们来把它封装成一个函数吧,用的时候直接调用就好了,防止代码冗余
//设置光标的坐标
void SetPos(short x, short y)
{
COORD pos = { x, y };
HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//设置标准输出上光标的位置为pos
SetConsoleCursorPosition(hOutput, pos);
}
那么SetPos就是设置光标位置的函数啦,想要修改直接传入两个坐标就可以实现目的啦
2.6 GetAsyncKeyState
SHORT GetAsyncKeyState(
int vKey
);
那么这个是什么意思呢?就是看返回的short类型的变量的最后一位二进制位是1还是0,那么我们就可以给它与一个1来检查
画图来看看吧:
与1的话,遇0为0,相同为1,这样就可以很好的检测出最后一位是1还是0了
那么来看看有哪些虚拟键码吧:
键码有很多,就不一 一列举了,大家下来可以自己去搜索,我这里把贪吃蛇用到的上下左右给截出来了 键码网址:虚拟键码 (Winuser.h) - Win32 apps | Microsoft Learn
3. 地图
3.1 <locale.h>本地化
3.2 类项
3.3 setlocale函数
声明:
setlocale(LC_ALL, "C");//C语言启动默认模式
setlocale(LC_ALL, ""); //本地模式
用这个函数切换到我们的本地模式后,就支持宽字符(汉字)或特殊符号的输出
3.4 宽字符的打印
#include <stdio.h>
#include<locale.h>
int main() {
setlocale(LC_ALL, "");
wchar_t ch1 = L'●';
wchar_t ch2 = L'刘';
wchar_t ch3 = L'帅';
wchar_t ch4 = L'★';
printf("%c%c\n", 'a', 'b');
wprintf(L"%lc\n", ch1);
wprintf(L"%lc\n", ch2);
wprintf(L"%lc\n", ch3);
wprintf(L"%lc\n", ch4);
return 0;
}
打印结果:
ab
●
刘
帅
★
好了,我们要用到的差不多都讲述了,那我们来着手写代码吧,写的过程中我会继续给大家讲述我的思路和相关知识
二,贪吃蛇的实现
我们还是老样子,分三个文件来实现:
test.c — 游戏的测试
snake.c — 游戏的功能实现
snake.h — 游戏的函数声明,以及类型声明
下面开始实现,我们游戏一开始就要先配置本地化环境,以方便可以在屏幕上打印宽字符,所以直接放在定义的main函数的刚开始
另外我们后期要生成贪吃蛇的食物,也肯定是一个随机数,现在也先把srand函数声明一下
setlocale需要的是<locale.h> ,srand需要的是<time.h>
我们接下来捋捋思路
初始化游戏
1.创建初始化环境
2.功能介绍
/3.打印地图
4.创建贪吃蛇
5.创建食物
6.设置游戏相关信息
那么我们的声明都是放在头文件里面的

然后画出总思路一步步实现:
我们这里分为三大类:游戏开始,游戏运行,游戏结束的善后工作
1.游戏开始的实现
1.123我们把游戏开始封装为一个函数,开始需要的其他功能也封装为一个个函数来实现
这些我们前面都已经讲了,可以回去看看
目前我们已经实现好前三个任务啦
1.4 接下来就是打印欢迎界面,那么我们就要用到最前面早就封装好的函数SetPos啦
这个函数只需要坐标,就可以在控制台的任意位置输出啦
下面来调用
这个打印界面完成以后就是这个样子啦
在按一下任意键继续就是这样
1.5 接下来就是创建地图啦:
//创建地图
void create_map()
{
int i = 0; //横58 竖26
//上
for (i = 0; i < 29; i++)
{
wprintf(L"%lc", wall);
}
SetPos(0, 26);
//下
for (i = 0; i <29; i++)
{
wprintf(L"%lc", wall);
}
//左
for (i = 1; i <=25; i++)
{
SetPos(0, i);
wprintf(L"%lc", wall);
}
//右
for (i = 1; i <=25; i++)
{
SetPos(56, i);
wprintf(L"%lc", wall);
}
}
这里我们也是用到了SetPos函数,刚开始从坐标为0开始它会一直下向后打印,我们这里就打印一个58*26的地图吧,因为我们横着打印的是宽字符,一个宽字符占两个字节,所以58我们只需要打印29次就可以刚好全部占满
□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
我们第一个循环打印了第一行围墙,接下来同样在(0,26)的位置,也就是26行的位置在打印29个宽字符的围墙,打印好以后就是这样:
□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
□□□□□□□□□□□□□□□□□□□□□□□□□□□□□
横的两行好打印,那么竖着的我们应该怎么办呢?也不难
我们从x为0和x为56的位置开始打印,每次循环都让y+1,这样就可以一直向下打印啦,那么都完了以后我们的地图就打印好啦:
1.6 接下来初始化蛇
//初始化贪吃蛇
void init_snake(Psnake ps)
{
psnake cur = NULL;
int i = 0;
for (i = 0; i < 5; i++) //整个循环既可以创建五个结点的空间,也可以把五个结点链接起来
{
cur = (psnake)malloc(sizeof(psnake));//申请蛇的结点空间
if (cur == NULL)
{
perror("malloc");
return;
}
cur->next = NULL; //刚开始谁都不要指向谁
cur->x = POS_x + 2 * i; //设置坐标
cur->y = 5;
//下面也是用循环顺便链接起来整个链表
//采用头插法链接蛇的身体
if (ps->snakehead==NULL) //为空的时候放进一个结点
{
ps->snakehead = cur;
}
else //不为空的时候,头插进链表,然后将头指针指向这个结点
{
cur->next = ps->snakehead;
ps->snakehead = cur;
}
}
cur = ps->snakehead; //先将蛇的头指针给了cur,然后遍历蛇整个身体链表
//打印蛇的身体,坐标为蛇的两个结点,每次将光标移动到下一个结点上,然后打印
while (cur)
{
SetPos(cur->x, cur->y);
wprintf(L"%lc",body);
cur = cur->next;
}
//设置关于蛇的一些情况
ps->dir = right; //蛇默认向右走
ps->status = ok; //情况默认为ok
ps->food_weight = 10; //每个食物分数为10
ps->score = 0; //总分数初始化为0
ps->sleep_time = 200; //以毫秒为单位
}
我们首先为蛇申请五个结点的空间作为刚开始的长度或链表大小,并且在循环里把坐标赋好,首先蛇肯定是一条,所以y坐标不能动,而因为要打印的是宽字符,所以x坐标必须为2的倍数,才不至于蛇出现一半在墙里面,一半在墙外面的情况
然后在循环里把五个结点头插,连接成一个链表,每次申请的cur就是一个新节点,然后一直头插,最后头指针放在最后一个结点,就像这样:
最后把我们初始化好的蛇打印出来,每次的位置就是蛇结点的坐标,在将一些游戏的情况设置一下,我们的蛇默认向右走,游戏运行情况为ok,每个食物权重为10分,总分数为0,蛇每走一步就会停一下,我们用肉眼是很难看出来的,每走一步暂停的时间为200毫秒,到了后面我们要让蛇减速的话就可以把时间增多,加速的话就把时间减少
1.7 创建食物
大概是这个思路:
//创建食物的随机函数
void create_food(Psnake ps)
{
int x = 0;
int y = 0;
again:
do
{
x = rand() % 53 + 2; //还得在墙体范围内
y = rand() % 25 + 1;
} while (x%2!=0); //食物x坐标为偶数,否则蛇吃不到,所以得判断
psnake cur = ps->snakehead; //接收蛇头指针
while (cur)//遍历判断食物和蛇身是不是重复,是的话goto重新生成
{
if (x == cur->x && y == cur->y)
{
goto again;
}
cur = cur->next;
}
//创建食物的结点
psnake food_=(snakeNode*)malloc(sizeof(snakeNode));
if (food_ == NULL)
{
perror("creat_food:");
return;
}
food_->x = x;
food_->y = y;
food_->next = NULL;
SetPos(x, y);
wprintf(L"%lc", food);
ps->snakefood = food_;
}
我们随机生成的食物首先必须在地图里面,所以需要设置一些限制条件,而且食物的坐标x和蛇的一样,也不能是单数,必须为2的倍数,然后用循环遍历蛇身,如果有食物的坐标x和y都和蛇的相等,那就goto到随机数之前重新生成,这些条件都判断完了之后,我们就放心的给食物申请结点空间,将坐标赋给食物结点的x和y,并且定位光标到随机坐标的位置,然后用wprintf打印食物,最后将贪吃蛇结构体食物的结点指向食物,我们这里为了避免麻烦,打印字符都用宏代替啦
我们这里完了以后,游戏开始的实现就完成啦,来看看吧:
右边的我们在第二部分去实现
2.游戏运行的实现
2.1.打印帮助信息
//打印右侧帮助信息
void print_help()
{
SetPos(65, 10);
wprintf(L"%ls", L"不能穿墙,不能咬到自己");
SetPos(65, 12);
wprintf(L"%ls", L"用↑.↓.←.→.来控制蛇移动");
SetPos(65, 14);
wprintf(L"%ls", L" 按F3加速,F4减速");
SetPos(65, 16);
wprintf(L"%ls", L"按ESC退出,按spacce暂停");
SetPos(80, 25);
wprintf(L"%ls", L"《-刘帅制作-》");
}
打印完以后就正式进入到了功能实现的门槛
2.2游戏逻辑运行
//游戏运行的逻辑
void Gamerun(Psnake ps)
{
//打印帮助信息
print_help();
do
{
//打印总分数和食物分值
SetPos(65, 8);
printf("食物分数:%d 总分数:%d \n", ps->food_weight, ps->score);
//看上下左右键有没有被按
if (KEY_PRESS(VK_UP) && ps->dir != down) //上
{
ps->dir = up;
}
else if (KEY_PRESS(VK_DOWN) && ps->dir != up)//下
{
ps->dir = down;
}
else if (KEY_PRESS(VK_LEFT) && ps->dir != right)//左
{
ps->dir = left;
}
else if (KEY_PRESS(VK_RIGHT) && ps->dir != left)//右
{
ps->dir = right;
}
else if (KEY_PRESS(VK_SPACE))
{
//暂停
Pause();
}
else if (KEY_PRESS(VK_ESCAPE))
{
//正常退出游戏
ps->status = Esc;
}
else if (KEY_PRESS(VK_F3))
{
//加速
if (ps->sleep_time > 80) //用休眠时间来做判断,休眠最大200毫秒,只能加速四次
{
ps->sleep_time -= 30;
ps->food_weight += 2;
}
}
else if (KEY_PRESS(VK_F4))
{
//减速
if (ps->food_weight > 2) //用食物分数来做减速的条件,最多分数到2的时候就不能减速了
{
ps->sleep_time += 30;
ps->food_weight -= 2;
}
}
snakeMove(ps); //蛇每次走一步的函数
Sleep(ps->sleep_time); //每走一步的休眠时间
} while (ps->status == ok); //情况为ok就可以正常运行游戏
}
我们将食物分数和总分数的打印放进循环里,因为他们会随着游戏情况变化,一进循环我们就来判断一下玩家的按键有没有按压,我们需要刚开始讲的那个宏
//定义按键有没有被按的宏
#define KEY_PRESS(vk) ((GetAsyncKeyState(vk)&1)?1:0)
将找好的虚拟键值放进宏里面去测试,这里我们还要判断一下,因为我们不能走相反的方向,比如蛇现在向右走,就不能向左走,其他三个按键也是一样都判断一下,如果按压了哪个键,那么我们就把蛇的方向改变为那个键指的方向
接下来判断其他按键,空格要暂停的话其实也很简单,我们只需要一个函数,然后死循环的用Sleep函数进行休眠就好了,可是我们不会一直暂停呀,所以我们需要做一个跳出死循环的条件,那就是空格下次如果被按了,那说明就是不要暂停啦,我们直接break跳出死循环:
//游戏暂停函数
void Pause()
{
while (1)
{
Sleep(200);
if (KEY_PRESS(VK_SPACE))
{
break;
}
}
}
接下来其他键我就一起说啦,判断Esc退出键,我们就把status设置为Esc,因为循环的条件就是status=ok,所以就可以退出游戏啦
而判断F3和F4加速减速也很简单,我们加减蛇每走一步的休眠时间就好啦,然后每次相应的也加减分数,但我们可不能让玩家一直加速或者减速,所以也得判断,加速做多可以有四次,休眠时间小于80就不可以加速啦,而减速每次减2的食物分数,当食物分数小于2时就不可以减啦
2.3 蛇每走一步函数
先上代码:
//蛇每走一步的函数
void snakeMove(Psnake ps)
{
//创建一个结点,表示蛇的下一个结点
psnake pnext = (psnake)malloc(sizeof(snakeNode));
if (pnext == NULL)
{
perror("snakeMove:");
return;
}
//判断蛇的方向以及下一个结点的坐标
switch (ps->dir)
{
case up:
pnext->x=ps->snakehead->x;
pnext->y=ps->snakehead->y - 1;
break;
case down:
pnext->x = ps->snakehead->x;
pnext->y = ps->snakehead->y + 1;
break;
case left:
pnext->x = ps->snakehead->x-2;
pnext->y = ps->snakehead->y;
break;
case right:
pnext->x = ps->snakehead->x+2;
pnext->y = ps->snakehead->y;
break;
}
//判断下一个结点是不是食物
if (is_food(pnext,ps))
{
//吃掉食物
Eatfood(pnext,ps);
pnext = NULL;
}
else
{
//不是食物
Nofood(pnext, ps);
}
//检测蛇是否撞墙
kill_bywall(ps);
//检测蛇是否撞到自己
kill_byself(ps);
}
2.3.1我们得先创建下⼀个节点,根据移动方向和蛇头的坐标,蛇移动到下⼀个位置的坐标,有四种可能性,蛇向四个方向走,分别判断:
2.3.2判断完以后,将坐标赋给蛇的下一个结点,然后继续判断这个结点是不是食物
只有两种可能,是或者不是
//判断是不是食物
int is_food(psnake pn, Psnake ps)
{
//是的话返回1,不是返回0
return (ps->snakefood->x == pn->x && ps->snakefood->y == pn->y);
}
我们直接封装一个函数,看食物的结点坐标等不等于pn的坐标,等于就是食物,返回1,不等于返回0
当回到判断里面以后,又会产生出了两个问题,是食物我们就吃掉,不是食物就作为蛇的下一个结点,头插进去然后准备打印
那么我们又会封装两个函数,是不是感觉一直在嵌套函数哈哈,不要绕晕哦
吃掉食物函数:
//吃掉食物函数
void Eatfood(psnake pn, Psnake ps)
{
//头插使食物指针指向蛇头指针,头插就会使蛇每次吃完食物变长
ps->snakefood->next = ps->snakehead;
ps->snakehead = ps->snakefood;
//free(pn);
//pn = NULL; //将食物指针头插到蛇链表上,然后释放掉另一个pn结点
//遍历打印贪吃蛇
psnake cur = ps->snakehead;//找到蛇头指针
while (cur)
{
SetPos(cur->x, cur->y); //打印之前先定位坐标
wprintf(L"%lc", body);
cur = cur->next;
}
//每次吃完食物,分数也加
ps->score += ps->food_weight;
//吃完并重新创建一个食物,调用之前的函数就好
create_food(ps);
}
如果下一个结点是食物,我们就把食物的结点指针头插指向链表,然后将蛇头指针指向刚头插进来的第一个结点,这样蛇每次吃掉食物就会变长一个结点,然后我们创建一个cur结点指向蛇头结点,遍历打印贪吃蛇,每次打印前都把要打印的贪吃蛇的每个结点的坐标定位好,每次吃完食物,总分数就加上一个食物的分数,最后我们既然吃掉一个食物,那肯定就要生成下一个随机食物,我们这里就直接调用上次的创建食物函数
不是食物函数:
//下一个位置不是食物函数
void Nofood(psnake pn, Psnake ps)
{
//头插下一个结点链接蛇头指针
pn->next = ps->snakehead;
ps->snakehead = pn;
//指向蛇头指针,开始遍历打印
psnake cur = ps->snakehead;
while(cur->next->next!=NULL) //当遍历到蛇尾巴的前一个结点的时候跳出循环
{
SetPos(cur->x, cur->y);
wprintf(L"%lc", body);
cur = cur->next;
}
//把光标定位到蛇尾巴的结点,打印两个空格(正好对应宽字符的两个字节),
// 要不然那个圆圈会一直在原地,就算蛇不吃食物也会变长
SetPos(cur->next->x, cur->next->y);
printf(" ");
free(cur->next->next);//释放尾巴结点
cur->next = NULL; //将目前蛇的最后一个结点的next置为NULL
}
如果下一个结点不是食物,那我们就把下一个结点头插进链表,然后使新节点成为蛇头指针,然后就开始打印贪吃蛇,但我们要想一个问题,蛇一直往前走会不会一直变长,每次不是食物都会向前走,但每次加一个结点是不是不合适呢?所以我们每次不是食物就加一个结点,然后减一个尾结点,这样保证贪吃蛇不吃食物的前提下,向前走一直都是原始的五个结点,那么我们就要在循环中判断啦,当遍历的蛇身结点的下一个结点的next为NULL时,我们就跳出循环,这时我们刚好打印了五个结点,但尾巴结点还在屏幕上呢 像下面这样:
所以我们需要定位到目前指针的下一个位置的坐标(尾巴结点坐标),然后打印空格,把贪吃蛇的结点●覆盖掉,这样蛇每次没吃食物移动就会保持原始长度啦!不要忘记最后把尾巴结点置为NULL喔!!!
2.3.3 判断蛇运行情况
现在我们的贪吃蛇就可以移动起来啦,但我们移动的过程中又会想到,贪吃蛇怎样算挂掉,然后退出游戏呢?那当然是撞到墙和撞到自己的身体
所以我分别封装两个函数来判断:
撞墙:
/判断撞墙的函数
// 拿头指针的坐标判断是否与墙有重合
void kill_bywall(Psnake ps)
{
if (ps->snakehead->x == 0 || ps->snakehead->x == 56
||ps->snakehead->y ==0 || ps->snakehead->y == 26)
{
ps->status = die_wall;
}
}
我们就拿蛇头指针的坐标来判断,如果跟墙的坐标重合,那肯定就是撞墙啦,但我们的地图是58*26的,其实x坐标得设置为等于56才算挂掉,还记得吗,我们打印的是宽字符,所以得是2的倍数,而58的话已经处于墙的最外面啦,所以得减2是56,我们判断完以后,就会用到之前设置的判断游戏情况的枚举啦,我们这时就把枚举变量设置为die_wall,就表示撞墙挂掉啦,然后do while循环就会检测到status不等于ok,然后就会退出游戏
撞自己:
//检测蛇是否撞到自己
// 遍历蛇身链表,然后看有没有和蛇头重复的坐标
void kill_byself(Psnake ps)
{
psnake cur = ps->snakehead->next;
while (cur)
{
if (ps->snakehead->x == cur->x &&
ps->snakehead->y == cur->y)
{
ps->status = die_self;
break;
}
cur = cur->next;
}
}
撞自己的话,我们采用遍历蛇链表的方式来检测,每走一步就看看蛇头指针等不等于蛇身的结点坐标,必须得x和y的坐标都相等,这样才说明撞到自己啦,然后我们直接把游戏情况的枚举变量设置为die_self,然后break跳出循环就不判断了,因为这时贪吃蛇已经挂掉啦
2.4 每步的休眠时间
我们这里非常简单,直接调用<Windows.h>里的Sleep函数,休眠时间就为ps->sleep_time,也就是200毫秒,
3. 游戏结束的善后工作
//游戏结束-善后工作
void Gameover(Psnake ps)
{
SetPos(24, 13);
//根据游戏状况总结话语
switch (ps->status)
{
case die_wall:
printf("您撞到墙了,游戏结束\n");
break;
case die_self:
printf("您撞到自己了,游戏结束\n");
break;
case Esc:
printf("主动退出\n");
break;
}
}
3.1 打印话语
我们最后用switch语句,根据定义的枚举变量来决定打印什么话语,然后回到测试函数里面
3.2 重新开始游戏
回来以后就可以问玩家要不要再来一把,那么这肯定又是一个循环我们在测试函数里面写一下:
//完成游戏逻辑
void test()
{
int ch = 0;
do
{
system("cls");//清屏,防止y一直在屏幕上
//创建贪吃蛇
Snake snake = { 0 };
//初始化游戏
//1.创建初始化环境
//2.功能介绍
// 3.打印地图
//4.创建贪吃蛇
//5.创建食物
//6.设置游戏相关信息
//游戏初始化
Gamestart(&snake);
//运行游戏
Gamerun(&snake);
//游戏结束-善后工作
Gameover(&snake);
//释放贪吃蛇
realese_snake(&snake);
SetPos(24, 14); //坐标
printf("还要再来一局吗?(Y/N):");
ch=getchar();
while (getchar()!='\n'); //防止一直输入的情况
} while (ch=='y' || ch=='Y');
SetPos(0, 27); //最后结束的时候把信息放在墙体下面
}
测试函数里面包括了我们贪吃蛇的所有功能实现,把这个整体作为一个循环,根据用户输入来判断是否重新开始游戏,那么循环条件就是输入值啦,有大Y也有小y,然后在输入下面加一个循环,防止用户乱输入,当用户输入选项以后,不管输入什么,我们都根据回车才做出反应
3.3 释放贪吃蛇
当然,我们每次游戏一结束,就立马释放贪吃蛇链表,然后在问玩家要不要继续开始游戏,继续开始的话就输入y或Y,然后进入三个大函数,游戏开始,运行和结束
三, C语言总结
这个贪吃蛇作为C语言基础学完的一个小项目,运用到了我们学习C语言中的许多知识,思想,还涉及了数据结构中的一些链表知识,对刚学完C语言的同学来说,是一个总结和复习自己学过知识的好机会,这是我们写的第一个小项目,只有500多行代码,但绝对不是我们的最后一个项目,我们要更加努力的去学习,写出更多的项目
少年的书桌上没有虚度的光阴,程序员是一个需要终身学习的职业,愿我们保持激情,继续奔赴下一个人才辈出的时代!