一、碎碎念
二、准备工作
三、最终效果
四、代码讲解
五、源码
一、碎碎念
事情起源是我发现我爸开始玩一些小游戏以防自己老年痴呆(真的很逗,我笑了好长时间),而且我也一直有做游戏的想法(且不想上课),那我就想着自己来写一个小游戏,于是我就在b站上找视频学习,随便点了一个开始看的,做的期间还是有一些疑惑,有幸得到了以为b站大佬的指点,做完这个游戏之后我发现,这个需要的C语言逻辑还没有之前做的登录系统需要的逻辑性强,游戏需要的更多是一种做游戏的逻辑,初学者如果想要巩固c语言逻辑和知识,建议还是去做登录系统,这个项目感觉有点玩的意思了,然后这个东西也是早就弄出来了,但是一直懒得重新捋思路......
这篇文章写一些老师视频里没有讲清楚的和我当时遇到问题的点和一些我的体会
下面是视频的链接
C语言必学项目:贪吃蛇!大一计算机专业巩固C语言基础常用项目,一个小时带你做出C语言入门级游戏!_哔哩哔哩_bilibiliC语言必学项目:贪吃蛇!大一计算机专业巩固C语言基础常用项目,一个小时带你做出C语言入门级游戏!_哔哩哔哩_bilibili
二、准备工作
平台:Visual Studio 2022
语言:C语言
需要具备的知识:c语言基础语法,数组,枚举,结构体,函数
首先这个项目的实现基本都是基于一个头文件里的函数,从而跳出小黑框
graphics.h这个头文件需要安装,所以用其他的c语言软件可能无法实现,具体的安装步骤可以看这个大佬的文章,很详细也很方便
C++语言图形库graphics.h的安装_NiuBenn的博客-CSDN博客_c语言图形库graphics.h
Visual Studio 2022这个平台可以去b站上搜一下教程啥的,也挺好装的
三、最终效果
效果大概就是这样,通过ASDW方向键来控制方向,然后撞到边界之后会从另一边的边界出来,自己撞到自己的话会死,会在小黑框里显示最终得分,按空格可以暂停游戏,按0退出游戏
四、代码详解
然后就是代码部分了,我就说一些关键一点的,其他的还是看b站的视频吧,这些问题也是我一开始遇到的。
1、结构体枚举和宏定义
首先是一堆结构体和枚举的定义还有宏定义,结构体和枚举的意义其实没有那么大,但是在调用的时候比较方便,跟登录系统的区别就是这个项目里的结构体等其实没有什么具体的意义,只是为了在整个项目中调用方便,感兴趣的可以看看我的源码体会一下
//一些宏定义 #define jieshu 500 #define HEIGHT 480 #define WIDETH 640
enum DIR //枚举类型表示蛇的方向
{
UP,
DOWN,
LEFT,
RIGHT,
};
struct food
{
int x;
int y; //坐标
bool flag; //状态标志位
int r; //半径大小
DWORD color;
}food;
struct snake
{
int size;//蛇的节数
int dir;//蛇的方向
int speed;//速度
POINT asdw[jieshu];//坐标
}snake;
2、显示函数
整个项目最关键的一个函数(我认为)就是下面这个这个函数的参数 xy都是坐标,最后一个参数是半径,贪吃蛇的身体和食物的显示都是通过这个函数来实现(图形库头文件中的函数)
void solidcircle(int x, int y, int radius); // 画填充圆(无边框)
3、下面是对蛇的身体的初始化,这种赋值方法就是为了让蛇头初始化给asdw[0],snake.asdw[i].x(y)都是坐标,可以用上面的函数来显示出蛇的身体
for (i = snake.size - 1; i >= 0; i--)//应该让蛇头赋值到asdw[0]
{
snake.asdw[i].x = 10 * (snake.size-i) + 20;
snake.asdw[i].y = 10;
}
4、蛇的运动
void snakemove()//移动蛇的函数
{
int i;
for (i = snake.size - 1; i > 0; i--)
{
snake.asdw[i] = snake.asdw[i - 1];
}
//根据不同方向进行处理
switch (snake.dir)
{
case RIGHT:
if (snake.asdw[0].x >=WIDETH)//撞墙判断
{
snake.asdw[0].x = 0;
}
snake.asdw[0].x+=snake.speed;//移动速度
break;
for (i = 1; i <= snake.size; i++)
{
if ((snake.asdw[0].x == snake.asdw[i].x) && (snake.asdw[0].y == snake.asdw[i].y))//是否碰到自身
{
printf("您输了,游戏结束,您的得分为%d", snake.size - 3);
Sleep(1000);
exit(0);
}
}
}
函数中的第一个for循环是为了让蛇的身体跟着头一起走,我一开始不理解这个函数为什么这么写,因为我觉得这么写的话,不就是蛇的后一节跟前一节一直重叠吗,但是此时注意i>0不是i>=0,所以这个过程就是这样的
后面就简单了,判断此时的方向,然后就该往哪边走就对坐标进行操作(这段代码只放了向上走部分),对坐标操作时要与speed关联,否则这个speed就没有意义了,因为前面已经操作了身体可以跟着移动,所以操作头的移动就可以了,还有一个撞墙的判断,如果撞了墙,就可以操作坐标,将蛇放到它该去的地方
最后是一个撞到自身的判断,sleep(1000)是为了让控制台停留一下,这样才能看到得分
5、通过键盘输入ASDW对蛇的方向进行控制
按键输入函数在conio.h头文件中,_getch()函数获取键盘输入,但是这个函数有一个问题,就是跟scanf效果一样,(为什么不用scanf,因为本项目跳出了小黑框,不在小黑框输入)如果不输入的话就会让程序卡在这里,所以要加一个判断,如果键盘有输入的话就判断,没输入的话,就正常走,利用了_kbhit(),如果有输入的话就返回1,没有返回0
这部分代码还有一个空格暂停和输入0退出的功能,按下空格后,进入死循环,直到下一次按下空格跳出循环,如果按下别的键则用continue跳出本次循环
若输入0,利用exit(0)退出程序
此处只列出了向上走部分
//通过按键改变蛇的方向
void key()
{
//如果不加东西就这样的话,会发现蛇会卡住,跟scanf一样的效果
// 所以要加个按键检测,如果按下了,则返回真,没按的话返回一个值,继续运行
if (_kbhit())
{
switch (_getch())//getch函数在conio.h头文件里
{
case 'W':
case 'w':
if (snake.dir != DOWN)//逻辑问题,向上的时候蛇头不能直接向下
{
snake.dir = UP;
}
break;
case ' ':
while (1)
{
switch (_getch())
{
case ' ':
return;
default:
continue;
}
}
case '0':
printf("您的得分为%dn",snake.size-3);
printf("游戏退出n");
exit(0);
default:
break;
}
}
}
6、吃食物的判断
void eatfood()
{
if (food.flag == true && snake.asdw[0].x >= food.x - food.r && snake.asdw[0].x <= food.x + food.r &&
snake.asdw[0].y >= food.y - food.r && snake.asdw[0].y <= food.y + food.r)
{
food.flag = false;
snake.size++;
}
if (food.flag == false)
{
food.r = rand() % 10 + 5;
food.color = RGB(rand() % 256, rand() % 256, rand() % 256);
//需要设置随机数种子,不然每次生成的都是同一个整数
//设置种子需要头文件,一般把时间作为种子,因为时间不断变化
food.x = rand() % 640;
food.y = rand() % 480;
food.flag = true;
}
}
第一个if里的判断条件,是在食物存在的条件下从多个维度来看蛇是否吃到了食物,如果吃到了食物,则food.flag=0,身体节数增加
第二个if里是在食物消失之后生成下一个食物的判断,里面放的是一堆初始化
五、总结
做出来之后,怎么说呢吧,毕竟是贪吃蛇,也没有很复杂的逻辑,这个也很基础,没有什么界面设计啥的,就就就就挺正常的吧,反正我爸是懒得玩我做的......
然后吧,第一次写博客,写的有点啰嗦,但是确实有不少我做的时候遇到的问题......
就这样吧!
六、源码
百度云链接
链接:https://pan.baidu.com/s/1v05zE02Lq4bBUvCj7dzXOw
提取码:hhhh



