96SEO 2026-02-19 22:49 0
毒鸡汤时间并不可真的帮我们去解决哪些问题它只不过是会把原来怎么也想不通的问题变得不再重要了。

作为零零后的我们想必贪吃蛇都玩过吧博主记得当时还在小霸王里面玩的这款小游戏十分怀念记忆深刻每次都是偷偷躲在被窝里面玩为了防止别抓基本上是躲在厕所里面玩上个厕所上个十年丑事不必再提。
作为一个程序员捏当然要简单的实现它啦也是为曾经的自己画上一个圆满的句号吧。
那咱们闲话少谈直接手撕贪吃蛇。
我们采用的是VS2019编译环境所以家人们准备好编译环境当然咱们上手不能直接上代码可能一开始上代码就是从入门到放弃我懂大家的捏。
咱们先介绍游戏到时候反手就说这个博主教我们怎么玩游戏取关必须取关家人们不先知道怎么玩你怎么知道游戏的逻辑给这些人拖出去斩了。
不知道大家还记得在C语言中我们实现了两款游戏一个是三子棋另一个是扫雷这些游戏和贪吃蛇是久负盛名的游戏它也和俄罗斯⽅块扫雷等游戏位列经典游戏的⾏列。
使⽤C语⾔在Windows环境的控制台中模拟实现经典⼩游戏贪吃蛇
C语⾔、数据结构链表、枚举、结构体、动态内存管理、预处理指令、win32
API这个咱们后面讲解这些基本上都学过哟像链表不知道大家能不能手撕链表不会的拖出去打30大板。
API应用程序可以充分挖掘Windows的32位操作系统的潜力。
Microsoft的所有32位平台都支持统一的API包括函数、结构、消息、宏及接口。
使用
API不但可以开发出在各种平台上都能成功运行的应用程序而且也可以充分利用每个平台特有的功能和属性。
在具体编程时程序实现方式的差异依赖于相应平台的底层功能的不同。
最显著的差异是某些函数只能在更强大的平台上实现其功能。
例如安全函数只能在Windows
NT操作系统下使用。
另外一些主要差别就是系统限制比如值的范围约束或函数可管理的项目个数等等。
有一些函数并不用于交互比如管理当前系统正在运行的进程、硬件系统状态的监视等等……这些函数只有一套但是可以被所有的Windows程序调用只要这个程序的权限足够高简而言之API是为程序所共享的。
为了达到所有程序能共享一套API的目的Windows采用了“动态链接库”的办法。
之所以叫“动态链接库”是因为这样的函数库的调用方式是“随用随取”而不是像静态链接库那样“用不用都要带上”。
像我们运行一个代码就有一个黑框框没错它就是控制台程序Win32
API我们是可以控制它滴终于有人可以管得住它了不然它还是一个野孩子。
我们可以使⽤cmd命令来设置控制台窗⼝的⻓宽设置控制台窗⼝的⼤⼩30⾏100列
API函数。
它⽤于从⼀个特定的标准设备标准输⼊、标准输出或标准错误中取得⼀个句柄⽤来标识不同设备的数值使⽤这个句柄可以操作设备。
简单的来讲就是可以用键盘控制控制台。
设置指定控制台屏幕缓冲区中的光标位置我们将想要设置的坐标信息放在COORD类型的pos中调用SetConsoleCursorPosition函数将光标位置设置到指定的位置。
将键盘上每个键的虚拟键值传递给函数函数通过返回值来分辨按键的状态。
函数后如果返回的16位的short数据中最⾼位是1说明按键的状态是按下如果最⾼是0说明按键的状态是抬起如果最低位被置为1则说明该按键被按过否则为0。
如果我们要判断⼀个键是否被按过可以检测GetAsyncKeyState返回值的最低值是否为1.
这里不得不讲一下控制台窗口的一些知识如果想在控制台的窗⼝中指定位置输出信息我们得知道该位置的坐标所以首先介绍一下控制台窗⼝的坐标知识。
控制台窗口的坐标如下所示横向的是X轴从左向右依次增长纵向是Y轴从上到下依次增长。
在游戏地图上我们打印墙体使⽤宽字符□打印蛇使用宽字符●打印食物使用宽字符★普通的字符是占⼀个字节的这类宽字符是占用2个字节。
这里再简单的讲⼀下C语言的国际化特性相关的知识过去C语言并不适合非英语国家地区使用。
C语言最初假定字符都是但自己的。
但是这些假定并不是在世界的任何地方都适用。
后来为了使C语言适应国家化C语言的标准中不断加入了国际化的支持。
比如加入和宽字符的类型
和宽字符的输⼊和输出函数加入和locale.h头文件其中提供了允许程序员针对特定
地区通常是国家或者说某种特定语言的地理区域调整程序行为的函数。
函数用于修改当前地区可以针对⼀个类项修改也可以针对所有类项。
setlocale
的第一个参数可以是前面说明的类项中的一个那么每次只会影响一个类项如果第一个参数是LC_ALL就会影响所有的类项。
当程序运行起来后想改变地区就只能显⽰调⽤setlocale函数。
用
函数就可以切换到本地模式这种模式下程序会适应本地环境。
比如切换到我们的本地模式后就支持宽字符汉字的输出等。
我们发现⼀个普通字符占⼀个字符的位置但是打印⼀个汉字字符占⽤2个字符的位置那么我们如果要在贪吃蛇中使⽤宽字符就得处理好地图上坐标的计算。
我们假设实现一个棋盘27行58列的棋盘行和列可以根据自己的情况修改再围绕地图画出墙
初始化状态假设蛇的长度是5蛇身的每个节点是●在固定的一个坐标处比如(24,
注意蛇的每个节点的x坐标必须是2个倍数否则可能会出现蛇的⼀个节点有一半儿出现在墙体中另外⼀般在墙外的现象坐标不好对齐。
关于食物就是在墙体内随机生成⼀个坐标x坐标必须是2的倍数坐标不能和蛇的身体重合然后打印★。
咱们从三个方面来讲解贪吃蛇的核心逻辑分析test.c主函数snake.h包含头文件snake.c主函数的实现跟我们玩链表差不多都是老套路了那贪吃蛇的实现正式上路咯启程。
像头文件这个东西必然是要包含一些头文件的当然这只是它的一部分作用像我们定义的链表为了在各个源文件都能使用我们就在头文件实现链表。
如果函数很多就把函数头包函数在头文件中方便调用那咱们看看在snake.h中有啥
{OK,//正常运行END_NORMAL,//按ESC退出KILL_BY_WALL,KILL_BY_SELF
_pSnake;//指向贪吃蛇头结点的指针pSnakeNode
_SleepTime;//每走一步休息的时间时间越短速度越快时间越长速度越慢enum
在这个文件中咱们实现贪吃蛇的函数实现时当然需要包含snake.h的文件啦需要用头文件里面的链表等.....
GetStdHandle(STD_OUTPUT_HANDLE);//影藏光标操作CONSOLE_CURSOR_INFO
CursorInfo;GetConsoleCursorInfo(hOutput,
CursorInfo);//获取控制台光标信息CursorInfo.bVisible
//隐藏控制台光标SetConsoleCursorInfo(hOutput,
CursorInfo);//设置控制台光标状态//打印欢迎界面WelComeToGame();//创建地图CreateMap();//初始化贪食蛇InitSnake(ps);//创建食物CreateFood(ps);
光标的移动需要多次实现为了我们方便使用移动光标位置所以我们直接实现这个函数。
不会有人跟我说光标是啥吧看我打不死你看到没
NULL;//获取标准输出的句柄(用来标识不同设备的数值)hOutput
GetStdHandle(STD_OUTPUT_HANDLE);//设置标准输出上光标的位置为posSetConsoleCursorPosition(hOutput,
其实这个函数大家可以自己设置把欢迎界面整的好看些像博主就比较懒就简单设计一下咯。
14);printf(欢迎来到贪吃蛇小游戏);SetPos(40,
25);system(pause);//pause是暂停system(cls);SetPos(20,
大家眼睛擦亮点计算坐标时不要计算错了可以根据自己设计自己喜欢的图
切记一定要把蛇初始状态需要是偶数倍初始化状态假设蛇的长度是5蛇身的每个节点是●在固定的一个坐标处比如(24,
5)处开始出现蛇连续5个节点。
注意蛇的每个节点的x坐标必须是2个倍数否则可能会出现蛇的⼀个节点有一半儿出现在墙体中另外⼀般在墙外的现象坐标不好对齐。
(pSnakeNode)malloc(sizeof(SnakeNode));//判断是否开辟成功if
NULL){perror(InitSnake:malloc);exit(-1);}//初始化蛇的位置在245cur-x
cur-next;}//对贪吃蛇的每个组成都初始化ps-_Status
10;//一个食物的分数//我们默认蛇开始向右走ps-_Dir
关于食物就是在墙体内随机生成⼀个坐标x坐标必须是2的倍数坐标不能和蛇的身体重合然后打印★。
食物可能与创建的蛇相同就必须从新创建食物。
这里采用again食物需要开辟空间的方便和蛇链接嘛毕竟是单链表食物的一些初始化
0);//x坐标必须是2的倍数//坐标不能和蛇的身体冲突pSnakeNode
(pSnakeNode)malloc(sizeof(SnakeNode));//判断if
NULL){perror(CreateFood()::malloc());return;}//初始化pFood-x
{//打印帮助信息PrintHelpInfo();//循环方向直到方向正确do{//打印得分SetPos(64,
(KEY_PRESS(VK_ESCAPE)){ps-_Status
(KEY_PRESS(VK_SPACE)){//暂停蛇移动Pause();}else
2;}}//蛇动的时间Sleep(ps-_SleepTime);//蛇的移动SnakeMove(ps);}
15);printf(1.不能撞墙不能咬到自己);SetPos(64,
17);printf(3.F3加速F4减速);SetPos(64,
cur-next;}//释放食物空间free(ps-_pFood);//加分数ps-_Score
ps-_FoodWeight;//创建食物CreateFood(ps);//新创建食物
(cur-next-next)//找最后一个节点就不再打印{//找坐标SetPos(cur-x,
cur-next;}//本来的尾的图案需要覆盖成空格SetPos(cur-next-x,
);//释放空间free(cur-next);cur-next
蛇既然要移动到下一个坐标所以需要开辟下一个位置的空间再判断蛇是否到食物。
(pSnakeNode)malloc(sizeof(SnakeNode));//判断if
NULL){perror(SnakeMove()::malloc());exit(-1);}pNext-next
ps-_pSnake-y;break;}//判断蛇头到达的坐标处是否是食物if
pNext);}//蛇是否撞墙KillByWall(ps);//蛇是否自杀KillBySelf(ps);}
END_NORMAL:printf(您主动退出游戏\n);break;case
KILL_BY_SELF:printf(自杀了,游戏结束\n);break;case
KILL_BY_WALL:printf(撞墙了游戏结束\n);break;}//释放蛇身的结点pSnakeNode
游戏善后释放资源GameEnd(snake);SetPos(20,
int)time(NULL));//游戏睡眠状态//调用函数test();return
NULL;//获取标准输出的句柄(用来标识不同设备的数值)hOutput
GetStdHandle(STD_OUTPUT_HANDLE);//设置标准输出上光标的位置为posSetConsoleCursorPosition(hOutput,
14);printf(欢迎来到贪吃蛇小游戏);SetPos(40,
25);system(pause);//pause是暂停system(cls);SetPos(20,
(pSnakeNode)malloc(sizeof(SnakeNode));//判断是否开辟成功if
NULL){perror(InitSnake:malloc);exit(-1);}//初始化蛇的位置在245cur-x
cur-next;}//对贪吃蛇的每个组成都初始化ps-_Status
10;//一个食物的分数//我们默认蛇开始向右走ps-_Dir
0);//x坐标必须是2的倍数//坐标不能和蛇的身体冲突pSnakeNode
(pSnakeNode)malloc(sizeof(SnakeNode));//判断if
NULL){perror(CreateFood()::malloc());return;}//初始化pFood-x
GetStdHandle(STD_OUTPUT_HANDLE);//影藏光标操作CONSOLE_CURSOR_INFO
CursorInfo;GetConsoleCursorInfo(hOutput,
CursorInfo);//获取控制台光标信息CursorInfo.bVisible
//隐藏控制台光标SetConsoleCursorInfo(hOutput,
CursorInfo);//设置控制台光标状态//打印欢迎界面WelComeToGame();//创建地图CreateMap();//初始化贪食蛇InitSnake(ps);//创建食物CreateFood(ps);
15);printf(1.不能撞墙不能咬到自己);SetPos(64,
17);printf(3.F3加速F4减速);SetPos(64,
20);printf(旧言专用版权);//getchar();
cur-next;}//释放食物空间free(ps-_pFood);//加分数ps-_Score
ps-_FoodWeight;//创建食物CreateFood(ps);//新创建食物
(cur-next-next)//找最后一个节点就不再打印{//找坐标SetPos(cur-x,
cur-next;}//本来的尾的图案需要覆盖成空格SetPos(cur-next-x,
);//释放空间free(cur-next);cur-next
(pSnakeNode)malloc(sizeof(SnakeNode));//判断if
NULL){perror(SnakeMove()::malloc());exit(-1);}pNext-next
ps-_pSnake-y;break;}//判断蛇头到达的坐标处是否是食物if
pNext);}//蛇是否撞墙KillByWall(ps);//蛇是否自杀KillBySelf(ps);}//暂停蛇移动
{//打印帮助信息PrintHelpInfo();//循环方向直到方向正确do{//打印得分SetPos(64,
(KEY_PRESS(VK_ESCAPE)){ps-_Status
(KEY_PRESS(VK_SPACE)){//暂停蛇移动Pause();}else
2;}}//蛇动的时间Sleep(ps-_SleepTime);//蛇的移动SnakeMove(ps);}
END_NORMAL:printf(您主动退出游戏\n);break;case
KILL_BY_SELF:printf(自杀了,游戏结束\n);break;case
KILL_BY_WALL:printf(撞墙了游戏结束\n);break;}//释放蛇身的结点pSnakeNode
{OK,//正常运行END_NORMAL,//按ESC退出KILL_BY_WALL,KILL_BY_SELF
_pSnake;//指向贪吃蛇头结点的指针pSnakeNode
_SleepTime;//每走一步休息的时间时间越短速度越快时间越长速度越慢enum
游戏善后释放资源GameEnd(snake);SetPos(20,
int)time(NULL));//游戏睡眠状态//调用函数test();return
今天内容就到这里啦时间过得很快大家沉下心来好好学习会有一定的收获的大家多多坚持嘻嘻成功路上注定孤独因为坚持的人不多。
那请大家举起自己的小说手给博主一键三连有你们的支持是我最大的动力回见。
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback