贪吃蛇小游戏项目总结(贪吃蛇小游戏设计总结)
wptr33 2025-06-09 00:39 12 浏览
经过了几天的思考和完善,我的贪吃蛇也是终于完成啦。属实是很开心的,当然完成这个项目的过程也是很曲折的。因此就要来一次全面的总结来对自己在这个过程中学到的新知识加以巩固。
这个项目不是完全以自己的知识范围所写出来的,我想到要开发贪吃蛇,第一个想到的问题就是怎么样让蛇显示到我想要它在的位置上呢。由于我之前并没有接触过SetConsoleCursorPosition()函数,因此这个问题就让我很困惑。因此我就开始看了慕课上的教程,于是知道了SetConsoleCursorPosition()函数可以解决我的这个问题。但是对这个函数比较陌生,因此我就在CSDN上查了这个函数加以学习。这个函数可以将你的光标移动到你想移动到的位置,这个函数是需要传入两个参数,但是参数并不是你想要移动的X,Y位置坐标,这里的参数是我之前没有接触到的。SetConsoleCursorPosition(hout,coord);coord是一个结构体,这个是由系统定义好的结构体,结构体中包括了两个成员,一个是x,一个是y,这就是你所想要移动到的坐标。那hout是什么呢?我查到的资料是说hout是一个句柄。我现在的知识量还不够特别深入详细地明白句柄的作用。但在使用这个函数的时候,只需要将coord中的X和Y两个元素赋值就可以进行操作啦。在项目中定义的gotoxy()函数中就用到了这个函数。而为了游戏的美观我又学习到了一个新的函数SetConsoleTextAttribute()函数,这个函数是API设置控制台窗口字体颜色和背景色的函数,可以改变字体颜色,让游戏更加美观。在实现键盘控制功能的时候又学习到了一个新的函数GetAsyncKeyState(VK_UP),这个函数是用来接收键盘的输入值,这里我们通过键盘的上下左右来操作蛇,直接就是UP,DOWN,RIGHT,LEFT来代表键盘的上下左右,这全都是由系统函数所规定的,直接调用即可。
除了上述三个新接触的函数,其它功能的实现都是在我已学知识范围内可以完成的或者是之前接触过的。本次我使用了刚学的链表完成了对蛇的创建。使用链表的好处就是在于实现蛇吃掉食物蛇身增加一节,以及蛇咬到自己,蛇撞墙这些功能时比较好理解,比较形象。相对于用数组来实现这些功能,个人觉得还是链表更简单一些。
新学到的知识总结完啦,下面就来总结一下自己在代码敲完之后,运行程序出现的问题,以及自己的解决方案。我在代码敲完之后,运行程序并进行测试,在多次运行程序之后,发现了这样的问题,那就是食物和蛇身重合的情况还是会出现。
一开始实现这个功能的代码如下:
/*
随机创建食物
*/
void createfood()
{
snake *food_1;
srand((unsigned)time(NULL)); //初始化随机数
food_1=(snake*)malloc(sizeof(snake)); //初始化food_1
while((food_1->x%2)!=0) //保证其为偶数,使得食物能与蛇头对齐,然后食物会出现在网格线上
{
food_1->x=rand()%52+2; //食物随机出现,食物的x坐标在2~52
}
food_1->y=rand()%24+1; //食物的y坐标在1~24
q=head;
while(q->next!=NULL)
{
if(q->x==food_1->x && q->y==food_1->y) //判断蛇身是否与食物重合
{
free(food_1); //如果蛇身和食物重合,那么释放食物指针
createfood(); //重新创建食物
}
q=q->next;
}
gotoxy(food_1->x,food_1->y);
food=food_1;
color(12);
printf("●"); //输出食物
}
这是最开始的代码,这部分我要实现的功能是随机生成食物,并判断是否与蛇身重合,如果重合,就重新生成食物。但从运行效果来看,这部分的代码还是有问题的。于是我想着去把这部分代码给改善一下。思考了很多天,也和同学讨论了这部分的问题,我也在CSDN上问了一些大神博主,最终找出了这部分代码出错的原因。出错的原因有两个:1.while(q->next! =NULL)这个while循环的判断条件导致蛇尾没有进行判断就跳出了循环。2.在while循环中递归调用了这个函数本身,假若第一个节点是与食物重合的,那么会第二次调用这个函数本身,此时第一次调用这个函数中的food_1是被释放掉的。如果第二次调用中食物不在蛇身上产生了,第二次调用结束,那么这个函数回到第一次调用的时候gotoxy(food_1->x,food_1->y);这句话就是违法的。第一个错误很简单,但是即使把第一个错误改掉之后,我发现第二个错误没法改。因此我得出了创建食物和判断是否与蛇身重合不能写在一个函数中的结论。于是我想把这个函数拆成两个函数,但具体改的方案不是我自己完成的,是我和同学一起讨论,最终完成了修改。
修改完的这部分代码如下:
/*
随机出现食物
*/
void createfood()
{
snake *food_1;
srand((unsigned)time(NULL)); //初始化随机数
food_1=(snake*)malloc(sizeof(snake)); //初始化food_1
do
{
food_1->x=rand()%(52/2)*2+2; //食物随机出现,食物的x坐标在2~52
food_1->y=rand()%24+1; //食物的y坐标在1~24
}
while(intobody(food_1->x,food_1->y));
gotoxy(food_1->x,food_1->y);
food=food_1;
color(12);
printf("●"); //输出食物
}
/*
判断食物是否与蛇身重合
*/
int intobody(int x,int y)
{
for(q=head;q!=NULL;q=q->next)
{
if(q->x==x&&q->y==y)
return 1;
}
return 0;
}
把原来的那个函数拆成了两个函数,一个用来创建食物,一个用来判断是否与蛇身重合,如果重合,第二个函数返回值为1,从而导致第一个函数继续循环,重新创建食物,直到不再和蛇身重合,第二个函数返回值为0,第一个函数跳出循环并且打印食物。这样修改十分具有可行性。在运行了很多次后都没有出现蛇身与食物重合的情况。自此,代码完善完成,贪吃蛇项目正式完工。
在这次的项目实践中我觉得自己独立思考问题的能力还有待提高,并且我觉得自己知识面太窄,需要想办法扩充自己的知识面。我的学习路径主要就是CSDN和百度,我认为CSDN上博主的讲解还是很好懂的,比较不错。后期我要试着开发其他一些小程序并且继续通过CSDN和百度不断学习,不断提高自己的编程能力,加油!!!
最后,想要源码的同学请点个赞并私聊我吧!
我是热爱剪辑与编程小刘同学!
相关推荐
- redis的八种使用场景
-
前言:redis是我们工作开发中,经常要打交道的,下面对redis的使用场景做总结介绍也是对redis举报的功能做梳理。缓存Redis最常见的用途是作为缓存,用于加速应用程序的响应速度。...
- 基于Redis的3种分布式ID生成策略
-
在分布式系统设计中,全局唯一ID是一个基础而关键的组件。随着业务规模扩大和系统架构向微服务演进,传统的单机自增ID已无法满足需求。高并发、高可用的分布式ID生成方案成为构建可靠分布式系统的必要条件。R...
- 基于OpenWrt系统路由器的模式切换与网页设计
-
摘要:目前商用WiFi路由器已应用到多个领域,商家通过给用户提供一个稳定免费WiFi热点达到吸引客户、提升服务的目标。传统路由器自带的Luci界面提供了工厂模式的Web界面,用户可通过该界面配置路...
- 这篇文章教你看明白 nginx-ingress 控制器
-
主机nginx一般nginx做主机反向代理(网关)有以下配置...
- 如何用redis实现注册中心
-
一句话总结使用Redis实现注册中心:服务注册...
- 爱可可老师24小时热门分享(2020.5.10)
-
No1.看自己以前写的代码是种什么体验?No2.DooM-chip!国外网友SylvainLefebvre自制的无CPU、无操作码、无指令计数器...No3.我认为CS学位可以更好,如...
- Apportable:拯救程序员,IOS一秒变安卓
-
摘要:还在为了跨平台使用cocos2d-x吗,拯救objc程序员的奇葩来了,ApportableSDK:FreeAndroidsupportforcocos2d-iPhone。App...
- JAVA实现超买超卖方案汇总,那个最适合你,一篇文章彻底讲透
-
以下是几种Java实现超买超卖问题的核心解决方案及代码示例,针对高并发场景下的库存扣减问题:方案一:Redis原子操作+Lua脚本(推荐)//使用Redis+Lua保证原子性publicbo...
- 3月26日更新 快速施法自动施法可独立设置
-
2016年3月26日DOTA2有一个79.6MB的更新主要是针对自动施法和快速施法的调整本来内容不多不少朋友都有自动施法和快速施法的困扰英文更新日志一些视觉BUG修复就不翻译了主要翻译自动施...
- Redis 是如何提供服务的
-
在刚刚接触Redis的时候,最想要知道的是一个’setnameJhon’命令到达Redis服务器的时候,它是如何返回’OK’的?里面命令处理的流程如何,具体细节怎么样?你一定有问过自己...
- lua _G、_VERSION使用
-
到这里我们已经把lua基础库中的函数介绍完了,除了函数外基础库中还有两个常量,一个是_G,另一个是_VERSION。_G是基础库本身,指向自己,这个变量很有意思,可以无限引用自己,最后得到的还是自己,...
- China's top diplomat to chair third China-Pacific Island countries foreign ministers' meeting
-
BEIJING,May21(Xinhua)--ChineseForeignMinisterWangYi,alsoamemberofthePoliticalBureau...
- 移动工作交流工具Lua推出Insights数据分析产品
-
Lua是一个适用于各种职业人士的移动交流平台,它在今天推出了一项叫做Insights的全新功能。Insights是一个数据平台,客户可以在上面实时看到员工之间的交流情况,并分析这些情况对公司发展的影响...
- Redis 7新武器:用Redis Stack实现向量搜索的极限压测
-
当传统关系型数据库还在为向量相似度搜索的性能挣扎时,Redis7的RedisStack...
- Nginx/OpenResty详解,Nginx Lua编程,重定向与内部子请求
-
重定向与内部子请求Nginx的rewrite指令不仅可以在Nginx内部的server、location之间进行跳转,还可以进行外部链接的重定向。通过ngx_lua模块的Lua函数除了能实现Nginx...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)