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

article/2025/10/26 8:38:11

贪吃蛇小程序,主要采用C语言描述,采用数组进行数据存储的图形化操作界面,会涉及一点点C++ 知识(特别少的一点点),但是有C语言基础就够用了,编译器:VS2015,会涉及部分库函数的安装及使用,我会在文章中给出详细的安装方法和解决方案。

文章目录

文章目录

前言

一、话不多述,先看游戏效果

二、实现步骤

1.新建工程文件及引入库函数

2.框架设计和代码实现 

实现设想:

1.游戏界面

2.绘制游戏元素

3.获取按键信息

4.操作贪吃蛇(重点)

5.贪吃长大

6.判断游戏结束

配乐:

总结



前言

在学习C语言的过程中,用小游戏来提高自己的代码实现能力是很不错的,贪吃蛇小程序可以在学习完数组的相关知识后有了一定的代码基础就可以尝试了,由于本游戏采用了图形化界面,可以作为平时的大作业和操作练手,下面我将带着用C语言写一个贪吃蛇小程序,包含图形界面和背景音乐,主要使用数组来实现数据存储,我使用的是VS2015,关于代码兼容性的问题,我会提及并解释,关于各种操作的原理和函数的调用,我会给出详细的解释和参考来源,对小白及其友好,下面,让我们开始吧!


一、话不多述,先看游戏效果

请原谅我那手残的操作 ε=(´ο`*))),(视频是有背景音乐的,但是由于视频不好上传,就只上传了GIF)

贪吃蛇实现效果
贪吃蛇效果

不过可以看到,实现效果还是不错的嘛,对于基本的按键操作都有很好的应对,并且在边界是可以自由穿过和穿出的,一定程度上降低了游戏难度,并且这里我设置的是半秒钟的延迟,对我来说已经比较快了,希望你们可以挑战更高的难度 ε≡٩(๑>₃<)۶ 

二、实现步骤


1.新建工程文件及引入库函数

新建文件:基本的新建文件及关闭安全检查在这里我就不提了,如果需要可以参考往期博文:如何关闭VS安全检查—三种方法

这里唯一要注意的是在添加文件时要添加 C++ 文件,而不是C文件,因为有使用easyx,必须是C++ 文件,具体细节可以参考EasyX说明文档,这是链接:easyx说明文档

引入库函数:因为我要进行的是图形操作,所以就会设计图形化的库函数引用,可以在VS编译器中是没有预装的,就可以自己选择安装了,这里我也有写过,可以参考往期博文:easyx等图形化库函数的使用  

好了,截止目前,我们要做的前期工作就基本完成了,下面要做的就是构建实现框架,编写代码了!(σ゚∀゚)σ..:*☆


2.框架设计和代码实现 

实现设想:

首先要有一个图形化的游戏界面,而不一个简单的操作台,也就是我们为什么要在上面要安装easyx了,我所设想的操作界面的大小是640*480的一个矩形,蛇体本身用方形表示,以10*10为基础构成,初始状态为三节的长度,没吃到一个 食物 ,身体长度就增加一节,并且蛇的操作是由方向键控制的,就需要在图形化界面里获取按键信息,并且要可以实时获得蛇的位置信息,我所设计的是可以穿过边界,并在另一侧出现,这样可以减少游戏难度,并且蛇的身体是要不断增加的,在这里我采用的是用数组来实现蛇的身体的增加,每吃到一个食物,将让该数组的长度加一,下面就让我们开始一步一步的实现这些设想吧。

1.游戏界面

首先就是要先实现这有640*480的游戏界面了,我选择定义了两个常量来存储这个数值,并且一起定义了蛇的最大长度在100

#define WIN_WIDTH 640
#define WIN_HEIGHT 480
#define MAX_SNAKE 100  //蛇的最大节数

然后就是初始化一个游戏界面了,initgraph 函数的作用就是产生一个图形化的窗口,参数分别是宽度、高度、属性。

具体可以参考说明文档:initgraph 说明文档

initgraph(WIN_WIDTH,WIN_HEIGHT,SHOWCONSOLE);//初始化一个图形窗口//具体参数见:https://docs.easyx.cn/zh-cn/initgraphprintf("\tWelcome! \n");printf("\tPlay Game Right Now!\n");

然后就是要设置蛇 的参数,并初始化各个元素了,在这里我使用的是数组来存储蛇的信息,其中就包括了蛇的长度,并且需要实时记录蛇头的方向(方便操作)和位置信息,还需要的就是要统计得分使用的分数了,下面是蛇的结构体:关于其详细的解释,我都写在注释里了关于 POINT 结构体,这个是属于库的结构体,可以直接使用。

struct Snake_tlg  //蛇的结构体
{int num;  // 身体的长度int dir;  //蛇的方向int score;  //分数int size;  //蛇的尺寸,身体和高度POINT coor[MAX_SNAKE];  //蛇的位置坐标。一个结构体数组//POINT 也时一个结构体,,可以通过选中转到定义来查看其具体结构,是在 windef.h中的/*typedef struct tagPOINT{LONG  x;LONG  y;} POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;*/}snake;

除了蛇的结构体,还要有食物的结构体,我们要记录食物的位置,以及食物是否存在,就是在蛇吃过它之后,它就要消失,并且可以继续产生新的食物,而且这里我还定义了食物的颜色信息,这样可以每次都产生一个不同颜色的食物,具体的实现我会放在 对应的代码中,下面是它的结构体:

struct Food_tlg  //食物的出现 结构体
{POINT fd;  //食物的坐标int flag;  //是否已经被蛇吃掉DWORD color;  //定义食物的颜色/*在DirectX程序中有些地方用DWORD(RGBA)格式表示颜色,其范围是[0 - 255]*/
}food;

下面就可以初始化各个游戏元素了,详细的注释我都放在代码里了,这里有一点是关于随机函数的问题,这里使用的是时间来产生随机值的,随机函数的具体使用,我在这个博客的注释中有解释过:三子棋游戏的操作实现_小鸡在啄米的博客-CSDN博客

rand 函数需要头文件<stdlib.h>,要保证每次产生的随机数都不同,就要借用srand,使用当前时间的毫秒数 来作为种子数,产生随机数

void GameInit()
{srand((unsigned int)time(NULL));	//time 的头文件是 time.h//定义蛇snake.num = 3;  //定义蛇初始有三节身体snake.dir = RIGHT;  //开始时蛇头向右snake.score = 0;  //开始时分数为0snake.size = 10;  //初始化蛇的身体大小snake.coor[2].x = 0;  //第三节身体(尾巴)的坐标snake.coor[2].y = 0;  // 由于初始化时就是在左上角的一个长条,所以y都是0snake.coor[1].x = 0+snake.size;  // 蛇的第二节(身体的坐标snake.coor[1].y = 0;snake.coor[0].x = 0+2*snake.size;  //蛇头,即第一节身体snake.coor[0].y = 0;//初始化食物food.fd.x = rand() % (WIN_WIDTH/10)*10;  //取模确保产生的随机值在范围内food.fd.y = rand() % (WIN_HEIGHT/10)*10;
//这里要先对10取商,再乘10是为了产生一个10的倍数,可以让蛇头和食物接触到,而不是每次都是一个随机数,无法判断food.flag = 1;  //初始化食物存在food.color = RGB(rand() % 256, rand() % 256, rand() % 256);//随机产生食物颜色}

在初始化基本完成之后,我们就可以进行下面的游戏操作了。

2.绘制游戏元素

关于这一块,主要是对游戏初始的一些设置,这里有个小心机就是在设置舌头的时候要用数组的第一个元素来保存,因为蛇头一定是不变的,永远都是在蛇尾变化,在这里我设置蛇在初始时是三个方块的大小,可以随着吃到食物的个数,随着变化。

设置食物的时候,可以通过绘制函数来绘制其他形状的食物,并且由于我之前在定义食物结构体的时候,有单独定义一个颜色,所以在这里食物的颜色是可以随机变化的,当然了每次的位置也是随机变化的

在设置分数的时候,会设计一个像图形界面输出的文字的问题,当时我按照教程编写的时候,总是无法正常的输出显示,很苦恼,最后在参考了这篇文章才成功解决,博主写的超级详细,很感激(〃'▽'〃),这里贴一下我参考的地址: https://codeabc.cn/yangw/a/error-c2665

所以在本代码中,我参考的是博主的第二个建议,在代码的顶端加上这两句代码,完美解决!!

#undef UNICODE
#undef _UNICODE
void GameDraw()
{setbkcolor(RGB(105, 160, 141));  //设置背景颜色,与web开发中的颜色设置一样cleardevice();  //清除其他元素//画蛇setfillcolor(YELLOW);int i;for (i = 0; i < snake.num; i++)  //每次都画一个矩形,共三次{setlinecolor(BLACK);fillrectangle(snake.coor[i].x,snake.coor[i].y,snake.coor[i].x + snake.size,snake.coor[i].y + snake.size);/*在 easyx 中,solidrectangle 这个函数用于画无边框的填充矩形,而fillrectangle用于画有边框的填充矩形void solidrectangle(int left,int top,int right,int bottom);void solidrectangle(矩形左部 x 坐标,	矩形顶部 y 坐标,	矩形右部 x 坐标,	矩形底部 y 坐标);*///printf("%d %d\n", snake.coor[i].x, snake.coor[i].y);  //用于效验坐标,在调试时使用}//画食物if (food.flag == 1) //要确保在食物被吃完之后就消失不见{setfillcolor(food.color);  //设置食物颜色fillellipse(food.fd.x, food.fd.y, food.fd.x + 10, food.fd.y + 10);  //设置食物形状}//显示分数char temp[20] = "";sprintf(temp,"分数:%d", snake.score);//SetBkMode(TRANSPARENT);outtextxy(20, 20, temp);//关于这一部分的详细解释参见:https://codeabc.cn/yangw/a/error-c2665}

好了,到现在,我们就成功实现了游戏的初始化和准备操作,下面就可以实时的对其进行控制了

3.获取按键信息

由于我们是在图形化界面进行的操作,所以我们要获取按键信息也与控制台获取按键信息有些许不同,在这里我主要是参考了其他编程大佬的说法(其实主要是当时查完资料没有保存好网址信息(╥╯^╰╥)):在这里的是我当时的一些理解,将当引用了,如果需要的话可以再自己找一下资料看看  ψ(*`ー´)ψ加油!

可以使用win32API来获取键盘消息,相比使用字符数组来存储并转换为ASCII要快捷很多
    GetAsyncKeyState函数的使用调用,相应按键是处于按下还是弹起状态
    若函数调用成功,返回值指定了自上次调用GetAsyncKeyState以来,指定的按键是否处于按下状态,
    以及该键现在是处于按下还是弹出。如果最高位被置1,表明键被按下,

如果是最低位被置1,则表明自前次调用GetAsyncKeyState一直处于按下状态。

在这里还有一点就是因为要针对方向键来接受信息,同时还可以排除其他操作,在这里使用了枚举类型来定义四个方向,主要是可以很方便的列举四个值,如果有什么不太清楚的可以参考这里的链接:C语言枚举类型(C语言enum用法)详解 

个人感觉写的已经很详细了。下面是枚举类型,在最前面定义的

enum DIR
{UP,DOWN,LEFT,RIGHT,
};

下面就是获取按键信息的主要函数了:有关的在注释中也有提及

void KeyControl()
{if (GetAsyncKeyState(VK_UP)&&snake.dir!=DOWN)//后面的条件确保了不可以进行反向操作{snake.dir = UP;}if (GetAsyncKeyState(VK_DOWN) && snake.dir != UP){snake.dir = DOWN;}if (GetAsyncKeyState(VK_LEFT) && snake.dir != RIGHT){snake.dir = LEFT;}if (GetAsyncKeyState(VK_RIGHT) && snake.dir != LEFT){snake.dir = RIGHT;}}

4.操作贪吃蛇(重点)

针对贪吃蛇的操作,主要是在蛇头上,然后蛇的身体只要依次移动到上一个位置就可以了,这样就可以实现贪吃蛇的移动效果(如果是每个的移动都和蛇头一样,那就是俄罗斯方块了),所以我们在这里我们只需要把数组中前一个元素的值 赋值 给后一个元素,就可以了:

int i;for (i = snake.num - 1; i > 0; i--)  //因为是对数组进行操作,所以这里要 -1,并且这里是i-- {snake.coor[i].x = snake.coor[i - 1].x;snake.coor[i].y = snake.coor[i - 1].y;}

下面就睡对于蛇头的操作了,从上一个函数中,我们已经获取了蛇头的信息,这里就可以用switch 语句进行匹配就可以了,在收到相应的信息就修改数组中蛇头的位置信息,并且由于我们的设定是可以穿墙的,就要让蛇在到达边界的时候立刻修改蛇头的位置,让其出现在另一侧,实现穿墙效果,下面是该函数的完整实现效果:

void SnakeMove()
{/*要操作蛇头的移动,蛇的身体随着蛇头一起运动,就是要从最后一节开始,让蛇的每一节身体都随着移动到它前一节身体的位置上*/int i;for (i = snake.num - 1; i > 0; i--)  //因为是对数组进行操作,所以这里要 -1,并且这里是i-- {snake.coor[i].x = snake.coor[i - 1].x;snake.coor[i].y = snake.coor[i - 1].y;}switch (snake.dir){case UP:snake.coor[0].y -= 10;/*这里要实现的是可以在窗口处自由进出因为记录的是蛇头方块左边的坐标,而这里我们要使蛇头在接触到边沿(是蛇头的右边)就进入下面的边界所以这里要有个+10,就是为了去掉蛇头自身的长度*/if (snake.coor[0].y +10 <= 0) {snake.coor[0].y = WIN_HEIGHT;}break; case DOWN:snake.coor[0].y += 10;if (snake.coor[0].y  >= WIN_HEIGHT){snake.coor[0].y = 0;}break;case LEFT:snake.coor[0].x -= 10;if (snake.coor[0].x + 10 <= 0){snake.coor[0].x = WIN_WIDTH;}break;case RIGHT:snake.coor[0].x += 10; if (snake.coor[0].x  >= WIN_WIDTH){snake.coor[0].x = 0;}break;default:printf("错误操作,请重新操作!"); break;}//snake.coor[0].x += 10;}

这事,我们就已经可以对蛇进行各种操作了。下面我们就可以实现吃食物的功能了。

5.贪吃长大

在设计食物这里要注意的是很重要的一点——食物的坐标,由于食物的坐标是随机产生的值, 我们可以通过取模来让其范围在游戏区域内,但是:蛇头的大小是10*10,如果坐标不是十的倍数,蛇头是无法识别并继续的,所以,这里就需要一点操作,让其直接产生在游戏区域内的,十的倍数的,我们可以先让结果取10的商,由于是整数类型,就可以舍掉其他部分,只保留整数,再乘以10就可以产生我们需要的结果了

同时,我们也要保证食物在被蛇头接触之后就要消失,所以在这里我使用的是食物的 flag值,只在flag 为0时产生新的食物,下面是这个函数的实现代码:

void EatFood()
{//判断蛇头和食物的坐标就可以了if (snake.coor[0].x == food.fd.x && snake.coor[0].y == food.fd.y&&food.flag==1){snake.num++;snake.score += 10;food.flag = 0;   //在吃完之后,就让食物不存在}if (food.flag == 0)  //当食物吃完之后就可以继续产生食物了{food.fd.x = rand() % (WIN_WIDTH / 10) * 10;  food.fd.y = rand() % (WIN_HEIGHT / 10) * 10;food.flag = 1; food.color = RGB(rand() % 256, rand() % 256, rand() % 256);}}

6.判断游戏结束

下面我们就可以判断游戏何时结束了,因为是数组存储的信息,我们就只需要判断蛇头(数组首元素)和其他身体的值有没有相等的就可以得出结论了,同时要在游戏结束时显示分数等结束信息,下面是实现代码:

void DontEatSelf()
{for (int i = 4; i < snake.num; i++){if (snake.coor[0].x == snake.coor[i].x && snake.coor[0].y == snake.coor[i].y){outtextxy(200, 200, "Game over!");_getch();  //保持停顿exit(666);}}
}

好了,到现在这个函数的各个部分的信息就已经全都实现了,最后我们就只需要在mine函数汇总设置一个死循环就可以保证一直调用这些函数了,并且在循环里要设置延迟时间,来保证游戏是可以操作的,这里我使用的是Sleep()函数,关于这个函数的具体使用,我在这个博客中有详细介绍:动画效果—时间函数

其他的时间函数我还很不了解,等到日后又机会我再学习补充(^_−)☆

下面是main函数的调用代码:

void main(void)
{initgraph(WIN_WIDTH,WIN_HEIGHT,SHOWCONSOLE);//初始化一个图形窗口printf("\tWelcome! \n");printf("\tPlay Game Right Now!\n");GameInit();  //初始化游戏元素while (1)  //使用死循环来保证可以一直游玩{{SnakeMove();t1 = t2;}t2 = GetTickCount;*/SnakeMove();  //先移动GameDraw();  //再画蛇EatFood();KeyControl(); DontEatSelf();Sleep(50);  //每次都要间隔半秒钟,才可以实时的看见,否则运行速度太快了,没法操作//同理这个操作也可以成为设置游戏难度的选项//Pause();}getchar();//用来防止 游戏窗口一闪而过closegraph();  //关闭游戏图形窗口
}

好了,到现在这个小游戏的完整效果就已经可以实现了,但是还有锦上添花的一点—— 背景音乐及音效

配乐:

这里由于我能力有限,就先只把背景音乐放上吧,这里需要两个特殊的头文件

#include <mmsyscom.h>//包含了可以播放音乐的头文件
#pragma comment(lib,"winmm.lib")//库文件

我选择在初始化那里就播放音乐(我用的是可商用的音乐素材(*^▽^*)),这里需要的函数是这两个:

mciSendString("open Carnival_De_Brazil.mp3 alias a",0,0,0);mciSendString("play a repeat",0,0,0);

如果需要其他音效的话,原理是类似的。

下面就是完整的实现代码了(包含背景音乐):

#define _CRT_SECURE_NO_WARNINGS 1
#undef UNICODE
#undef _UNICODE
/*
自己创建窗口
左上角为(0,0),横着为x轴,竖着为y轴*/#include <stdio.h>
#include <Windows.h>
#include <graphics.h>
#include <time.h>
#include <stdlib.h>#include <mmsyscom.h>//包含了可以播放音乐的头文件
#pragma comment(lib,"winmm.lib")//库文件#include <conio.h>//用宏定义了窗口的显示宽高
#define WIN_WIDTH 640
#define WIN_HEIGHT 480
#define MAX_SNAKE 100  //蛇的最大节数enum DIR
{UP,DOWN,LEFT,RIGHT,};struct Snake_tlg  //蛇的结构体
{int num;  // 身体的长度int dir;  //蛇的方向int score;  //分数int size;  //蛇的尺寸,身体和高度POINT coor[MAX_SNAKE];  //蛇的位置坐标。一个结构体数组//POINT 也时一个结构体,,可以通过选中转到定义来查看其具体结构,是在 windef.h中的/*typedef struct tagPOINT{LONG  x;LONG  y;} POINT, *PPOINT, NEAR *NPPOINT, FAR *LPPOINT;*/}snake;struct Food_tlg  //食物的出现 结构体
{POINT fd;  //食物的坐标int flag;  //是否已经被蛇吃掉DWORD color;  //定义食物的颜色/*在DirectX程序中有些地方用DWORD(RGBA)格式表示颜色,其范围是[0 - 255]*/
}food;void GameInit();  //初始化游戏元素
void GameDraw();  //创建贪吃蛇
void SnakeMove();  // 操作蛇的移动
void KeyControl();  //控制方向函数
void EatFood();  //吃食物
void DontEatSelf();  //游戏结束判断void Pause();  //游戏暂停void main(void)
{initgraph(WIN_WIDTH,WIN_HEIGHT,SHOWCONSOLE);//初始化一个图形窗口//具体参数见:https://docs.easyx.cn/zh-cn/initgraphprintf("\tWelcome! \n");printf("\tPlay Game Right Now!\n");GameInit();  //初始化游戏元素while (1)  //使用死循环来保证可以一直游玩{SnakeMove();  //先移动GameDraw();  //再画蛇EatFood();KeyControl(); DontEatSelf();Sleep(50);  //每次都要间隔半秒钟,才可以实时的看见,否则运行速度太快了,没法操作//同理这个操作也可以成为设置游戏难度的选项Pause();}getchar();//用来防止 游戏窗口一闪而过closegraph();  //关闭游戏图形窗口
}void GameInit()
{srand((unsigned int)time(NULL));	//time 的头文件是 time.h//定义蛇snake.num = 3;  //定义蛇初始有三节身体snake.dir = RIGHT;  //开始时蛇头向右snake.score = 0;  //开始时分数为0snake.size = 10;  //初始化蛇的身体大小snake.coor[2].x = 0;  //第三节身体(尾巴)的坐标snake.coor[2].y = 0;  // 由于初始化时就是在左上角的一个长条,所以y都是0snake.coor[1].x = 0+snake.size;  // 蛇的第二节(身体的坐标snake.coor[1].y = 0;snake.coor[0].x = 0+2*snake.size;  //蛇头,即第一节身体snake.coor[0].y = 0;//初始化食物food.fd.x = rand() % (WIN_WIDTH/10)*10;  //取模确保产生的随机值在范围内food.fd.y = rand() % (WIN_HEIGHT/10)*10;
//这里要先对10取商,再乘10是为了产生一个10的倍数,可以让蛇头和食物接触到,而不是每次都是一个随机数,无法判断food.flag = 1;  //初始化食物存在food.color = RGB(rand() % 256, rand() % 256, rand() % 256);//随机产生食物颜色mciSendString("open Carnival_De_Brazil.mp3 alias a",0,0,0);mciSendString("play a repeat",0,0,0);}void GameDraw()
{setbkcolor(RGB(105, 160, 141));  //设置背景颜色,与web开发中的颜色设置一样cleardevice();  //清除其他元素//画蛇setfillcolor(YELLOW);int i;for (i = 0; i < snake.num; i++)  //每次都画一个矩形,共三次{setlinecolor(BLACK);fillrectangle(snake.coor[i].x,snake.coor[i].y,snake.coor[i].x + snake.size,snake.coor[i].y + snake.size);/*在 easyx 中,solidrectangle 这个函数用于画无边框的填充矩形,而fillrectangle用于画有边框的填充矩形void solidrectangle(int left,int top,int right,int bottom);void solidrectangle(矩形左部 x 坐标,	矩形顶部 y 坐标,	矩形右部 x 坐标,	矩形底部 y 坐标);*///printf("%d %d\n", snake.coor[i].x, snake.coor[i].y);  //用于效验坐标,在调试时使用}//画食物if (food.flag == 1) //要确保在食物被吃完之后就消失不见{setfillcolor(food.color);  //设置食物颜色fillellipse(food.fd.x, food.fd.y, food.fd.x + 10, food.fd.y + 10);  //设置食物形状}//显示分数char temp[20] = "";sprintf(temp,"分数:%d", snake.score);//SetBkMode(TRANSPARENT);outtextxy(20, 20, temp);}void KeyControl()
{if (GetAsyncKeyState(VK_UP)&&snake.dir!=DOWN)//后面的条件确保了不可以进行反向操作{snake.dir = UP;}if (GetAsyncKeyState(VK_DOWN) && snake.dir != UP){snake.dir = DOWN;}if (GetAsyncKeyState(VK_LEFT) && snake.dir != RIGHT){snake.dir = LEFT;}if (GetAsyncKeyState(VK_RIGHT) && snake.dir != LEFT){snake.dir = RIGHT;}}void SnakeMove()
{/*要操作蛇头的移动,蛇的身体随着蛇头一起运动,就是要从最后一节开始,让蛇的每一节身体都随着移动到它前一节身体的位置上*/int i;for (i = snake.num - 1; i > 0; i--)  //因为是对数组进行操作,所以这里要 -1,并且这里是i-- {snake.coor[i].x = snake.coor[i - 1].x;snake.coor[i].y = snake.coor[i - 1].y;}switch (snake.dir){case UP:snake.coor[0].y -= 10;/*这里要实现的是可以在窗口处自由进出因为记录的是蛇头方块左边的坐标,而这里我们要使蛇头在接触到边沿(是蛇头的右边)就进入下面的边界所以这里要有个+10,就是为了去掉蛇头自身的长度*/if (snake.coor[0].y +10 <= 0) {snake.coor[0].y = WIN_HEIGHT;}break; case DOWN:snake.coor[0].y += 10;if (snake.coor[0].y  >= WIN_HEIGHT){snake.coor[0].y = 0;}break;case LEFT:snake.coor[0].x -= 10;if (snake.coor[0].x + 10 <= 0){snake.coor[0].x = WIN_WIDTH;}break;case RIGHT:snake.coor[0].x += 10; if (snake.coor[0].x  >= WIN_WIDTH){snake.coor[0].x = 0;}break;default:printf("错误操作,请重新操作!"); break;}//snake.coor[0].x += 10;}void EatFood()
{//判断蛇头和食物的坐标就可以了if (snake.coor[0].x == food.fd.x && snake.coor[0].y == food.fd.y&&food.flag==1){snake.num++;snake.score += 10;food.flag = 0;   //在吃完之后,就让食物不存在}if (food.flag == 0)  //当食物吃完之后就可以继续产生食物了{food.fd.x = rand() % (WIN_WIDTH / 10) * 10;  food.fd.y = rand() % (WIN_HEIGHT / 10) * 10;food.flag = 1; food.color = RGB(rand() % 256, rand() % 256, rand() % 256);}}void DontEatSelf()
{for (int i = 4; i < snake.num; i++){if (snake.coor[0].x == snake.coor[i].x && snake.coor[0].y == snake.coor[i].y){outtextxy(200, 200, "Game over!");_getch();  //保持停顿exit(666);}}
}void Pause()
{if (_getch() == 32)  //32表示空格{//while (_getch() != ' ');while (1){_getch();}}}

完成!!ヾ(๑╹◡╹)ノ"



总结

好了,到现在就完整的实现了贪吃蛇的游戏效果,通过这个程序的编程实现,对于图形化操作界面、数组的深入、游戏逻辑的判断等等都有了更深入的了解,对于编程的提高有很大的帮助,当然了,这个程序现在也还有遗憾的地方,就是不能在任意时刻停止,我会继续更新然后实现这个更完美的效果的!(>ω・* )ノ

感谢观赏,一起提高,慢慢变强。


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

相关文章

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;动态是指存储阵列需要不断的刷新来保证…

sdram简易控制器设计

耗时一周&#xff0c;终于完成sdram简易控制器的所有代码设计&#xff0c;其中感谢开源骚客 – 邓堪文老师在b站发布的相关视频学习教材&#xff1b;其中仿真模块及所使用到的sdram仿真文件来源于开源骚客&#xff1b; 因为时间较为紧迫&#xff0c;其中就不做代码的一些注释&…

基于FPGA的SDRAM控制器设计(一)

基于FPGA的SDRAM控制器设计&#xff08;一&#xff09; 1. SDRAM控制器整体框架2.UART_RX模块3.UART_TX模块4. RX与TX模块的整合5.需要注意的问题6.代码7.参考资料 1. SDRAM控制器整体框架 图1.1整体框架 PC端通过串口模块UART_RX发送读写命令以及数据到Cmd_encode模块&#xf…

基于FPGA的SDRAM控制器设计(1)

基于FPGA的SDRAM初始化配置 SDRAM简述SDRAM的引脚及作用SDRAM初始化时序控制SDRAM上电时序代码SDRAM测试模块的代码仿真测试结果参考文献总结 SDRAM简述 SDRAM&#xff08; Synchronous Dynamic Random Access Memory&#xff09;&#xff0c;同步动态随机存储器。同步是指 Me…

FPGA进阶(3):SDRAM读写控制器的设计与验证

文章目录 第50讲&#xff1a;SDRAM读写控制器的设计与验证理论部分设计与实现1. sdram_ctrlsdram_initsdram_a_refsdram_writesdram_readsdram_arbitsdram_ctrl 2. sdram_topfifo_ctrlsdram_top 3. uart_sdramuart_rxuart_txfifo_readuart_sdram 第50讲&#xff1a;SDRAM读写控…

SDRAM

简介、优缺点、历史 1、译为“同步动态随机存取内存”&#xff0c;区别于异步DRAM。SRAM是异步静态存储器。 2、同步(Synchronous)&#xff1a;与通常的异步 DRAM 不同&#xff0c; SDRAM 存在一个同步接口&#xff0c;其工作时钟的时钟频率与对应控制器(CPU/FPGA上的读写控制…