超详细C语言带你吃透贪吃蛇游戏之精髓

Posted 菜鸟要飞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了超详细C语言带你吃透贪吃蛇游戏之精髓相关的知识,希望对你有一定的参考价值。

设为 “星标”,和12万程序员一起成长!

文章目录


01. 开发背景

02. 功能介绍

03. 欢迎界面设计

  • 3.1 常用终端控制函数

  • 3.2 设置文本颜色函数

  • 3.3 设置光标位置函数

  • 3.4 绘制字符画(蛇)

  • 3.5 欢迎界面函数

04. 游戏帮助界面设计

05. 退出游戏实现

06. 游戏逻辑

  • 6.1 按下ESC键结束游戏

  • 6.1 判断是否撞到墙

  • 6.3 判断是否咬到自己

07. 游戏失败界面设计

  • 7.1 游戏失败界面边框设计

  • 7.2 撞墙失败界面

  • 7.3 咬到蛇身失败界面

  • 7.4 ESC结束游戏界面

  • 7.5 界面添加选择

  • 7.6 写文件实现

08. 一起来找茬

09. 项目扩展

10. 项目总结

【超详细C语言】带你吃透贪吃蛇游戏之精髓


01. 开发背景


贪吃蛇起源于西方,来自于蛇骗夏娃和亚当偷吃禁果的神话。人们为了说明蛇的一个“贪”字,开发出了贪吃蛇游戏。本公开课使用C语言开发一个贪吃蛇游戏。

贪吃蛇最初为人们所知的是诺基亚手机附带的一个小游戏,它伴随着诺基亚手机走向世界。现在的贪吃蛇出现了许多衍生版本,并被移植到各种平台上。


通过本案例的学习,大家可以学到:


  • Visual Studio 2017开发环境

  • C语言中的三大结构和函数

  • C语言中动态内存申请和释放

  • C语言中文件基本操作

  • C语言中的简单单向链表

  • 控制终端基本设置和监听按键

  • C语言简单游戏开发流程

  • C语言简单游戏开发调试技巧


02. 功能介绍


贪吃蛇的游戏规则也很简单,具体为:蛇出现在封闭的空间中,同时在地图上会随机出现食物,玩家通过键盘上的上下左右方向键来控制蛇的前进方向。蛇头撞到食物,则食物消失,表示被蛇吃掉了,蛇身增加一节,增加玩家的得分。接着又随机出现一个食物,等待蛇来吃。如果蛇在前进的过程中撞到墙或者咬到蛇身或者玩家按下ESC键,则游戏退出。

【超详细C语言】带你吃透贪吃蛇游戏之精髓


项目演示


03. 欢迎界面设计


欢迎界面如下:

【超详细C语言】带你吃透贪吃蛇游戏之精髓


3.1 常用终端控制函数

SetConsoleTextAttribute函数介绍

BOOL SetConsoleTextAttribute(HANDLE hConsoleOutput,WORD wAttributes);功能:设置控制台文本属性(颜色),可以设置前景色FOREGROUND(文本颜色)和背景色BACKGROUND


SetConsoleTextAttribute官方文档介绍请参考网址:https://docs.microsoft.com/en-us/windows/console/setconsoletextattribute


参考示例:

HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE); /* 获取标注输出句柄 */SetConsoleTextAttribute(hOut, FOREGROUND_BLUE); /* 设置控制台颜色,前景色为蓝色*/SetConsoleTextAttribute(hOut, BACKGROUND_RED);  /* 背景色为红色 */


SetConsoleCursorPosition函数介绍

BOOL SetConsoleCursorPosition(HANDLE hConsoleOutput, COORD dwCursorPosition);功能:设置控制台光标坐标


SetConsoleCursorPosition官方文档介绍请参考网址:https://docs.microsoft.com/en-us/windows/console/setconsolecursorposition


参考示例:

COORD pos = {x, y};/* x是横坐标 y是纵坐标 */HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE); /* 获取标注输出句柄 */SetConsoleCursorPosition(hOut,pos);     /* 设置控制台光标坐标(设备句柄, 光标坐标) */


3.2 设置文本颜色函数

//设置终端字体颜色int setColor(int c){ //GetStdHandle: 获取指定的标准设备的句柄 //STD_OUTPUT_HANDLE 标准输出句柄 //c 颜色值 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);
return 0;}


十进制颜色对照表:


【超详细C语言】带你吃透贪吃蛇游戏之精髓


3.3 设置光标位置函数

//设置光标的坐标int gotoXY(int x, int y){ COORD c; //设置横坐标 c.X = x; //设置纵坐标 c.Y = y;
//设置光标的位置 SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
return 0;}


3.4 绘制字符画(蛇)

参考代码:

//绘制字符画 --蛇int printSnake(void){ //清屏 system("cls");
gotoXY(35, 1); setColor(6); printf("/^\\/^\\"); //蛇眼睛
gotoXY(34, 2); printf("|__| O|"); //蛇眼睛
gotoXY(33, 2); setColor(2); printf("_");
gotoXY(25, 3); setColor(12); printf("\\/"); //蛇信
gotoXY(31, 3); setColor(2); printf("/");
gotoXY(37, 3); setColor(6); printf(" \\_/"); //蛇眼睛
gotoXY(41, 3); setColor(10); printf(" \\");
gotoXY(26, 4); setColor(12); printf("\\____"); //舌头
gotoXY(32, 4); printf("_________/");
gotoXY(31, 4); setColor(2); printf("|");
gotoXY(43, 4); setColor(10); printf("\\");
gotoXY(32, 5); setColor(2); printf("\\_______"); //蛇嘴
gotoXY(44, 5); setColor(10); printf("\\");
gotoXY(39, 6); printf("| | \\"); //下面都是画蛇身
gotoXY(38, 7); printf("/ / \\");
gotoXY(37, 8); printf("/ / \\ \\");
gotoXY(35, 9); printf("/ / \\ \\");
gotoXY(34, 10); printf("/ / \\ \\");
gotoXY(33, 11); printf("/ / _----_ \\ \\");
gotoXY(32, 12); printf("/ / _-~ ~-_ | |");
gotoXY(31, 13); printf("( ( _-~ _--_ ~-_ _/ |");
gotoXY(32, 14); printf("\\ ~-____-~ _-~ ~-_ ~-_-~ /");
gotoXY(33, 15); printf("~-_ _-~ ~-_ _-~");
gotoXY(35, 16); printf("~--______-~ ~-___-~");
return 0;}


测试代码如下:

int main(){
//设置控制台的宽高 system("mode con cols=100 lines=30");
printSnake();
system("pause"); return 0;}


测试效果如下:


【超详细C语言】带你吃透贪吃蛇游戏之精髓


3.5 欢迎界面函数

界面设计分析:


【超详细C语言】带你吃透贪吃蛇游戏之精髓


参考代码:

//欢迎界面int welcomGame(void){ int i; int j;
int n = 0;
//绘制字符画蛇 printSnake();
//输出文字 setColor(11); gotoXY(45, 18); printf("贪吃蛇游戏");
setColor(14);
//边框范围20--26行 27--74列 for (i = 20; i <= 26; i++) { for (j = 27; j <= 74; j++) { gotoXY(j, i); if (i == 20 || i == 26) { printf("-"); } else if (j == 27 || j == 74) { printf("|"); } } }
setColor(12); gotoXY(35, 22); printf("1. 开始游戏");
gotoXY(55, 22); printf("2. 游戏说明");
gotoXY(35, 24); printf("3. 退出游戏");
gotoXY(27, 27); printf("请选择[1 2 3]: ");
scanf("%d", &n); //清空换行符 getchar(); return n;}


主函数参考代码如下:

int main(){ int choice;
//设置控制台的宽高 system("mode con cols=100 lines=30");
while (1) { choice = welcomGame();
switch (choice) { //开始游戏 case 1: printf("开始游戏"); break;
//游戏说明 case 2: printf("游戏说明"); break;
//退出游戏 case 3: break; default: setColor(12); gotoXY(45, 28); printf("请做出有效选择[1~3]"); //输入任意键 getchar(); } }
system("pause"); return 0;}


04. 游戏帮助界面设计

游戏说明模块如下:


【超详细C语言】带你吃透贪吃蛇游戏之精髓


游戏帮助界面参考代码:

//游戏帮助界面int aboutGame(void){ int i = 0; int j = 0;
//清屏 system("cls");
setColor(13); gotoXY(44, 3); printf("游戏说明");
setColor(2); //画出边框 //6~22行 20~75列 for (i = 6; i <= 22; i++) { for (j = 20; j <= 75; j++) { gotoXY(j, i); //画上下边框 if (i == 6 || i == 22) { printf("="); } else if (j == 20 || j == 75) { printf("||"); } } }
setColor(3); gotoXY(30, 8); printf("★ 1.不能撞到墙壁,不能咬到自己");
setColor(5); gotoXY(30, 11); printf("★ 2.F1加速前进,F2减速前进");
setColor(11); gotoXY(30, 14); printf("★ 3.使用空格暂停游戏和继续游戏");
setColor(13); gotoXY(30, 17); printf("★ 4.使用方向键控制前进的方向");
setColor(14); gotoXY(30, 20); printf("★ 5.按下ESC键退出游戏");
setColor(12); gotoXY(22, 24); printf("按下回车键返回主界面...");
getchar();
return 0;}


主函数代码修改如下:

int main(){ int choice;
//设置控制台的宽高 system("mode con cols=100 lines=30");
while (1) { choice = welcomGame();
switch (choice) { //开始游戏 case 1: printf("开始游戏"); break;
//游戏说明 case 2: aboutGame(); break;
//退出游戏 case 3: break; default: setColor(12); gotoXY(45, 28); printf("请做出有效选择[1~3]"); //输入任意键 getchar(); } }
system("pause"); return 0;}


05. 退出游戏实现

在主菜单中, 当用户选择3的时候,直接退出游戏


在主函数case 3中添加如下代码:

//退出游戏case 3: exit(0); break;


06. 游戏逻辑

6.1 按下ESC键结束游戏

在moveKeyControl函数中添加如下代码片段

//按下F2减速if (GetAsyncKeyState(VK_F2)){ speedDown();}
//按下ESC键 结束游戏if (GetAsyncKeyState(VK_ESCAPE)){  endStatus = 3; break;}


6.2 判断是否撞到墙

参考代码:

//判断是否撞墙int isHitWall(void){ if (head->x == 0 || head->x == 56 || head->y == 0 || head->y == 26) { return 1; }}


在snake.c文件moveKeyControl函数中添加如下代码:

Sleep(sleepTime);
moveSnake();
//判断是否撞墙if (isHitWall()){ endStatus = 1;
break;}


6.3 判断是否咬到自己

//判断是否咬到自己int isBitSelf(void){ snake_t *tmp = NULL;
tmp = head->next; while (NULL != tmp) { if (tmp->x == head->x && tmp->y == head->y) { return 1; } tmp = tmp->next; }
return 0;}


在snake.c文件moveKeyControl函数中添加如下代码:

//判断是否撞墙 if (isHitWall()) { endStatus = 1;
break; }
//判断是否咬到自己 if (isBitSelf()) { endStatus = 2;
break; }


07. 游戏失败界面设计

7.1 游戏失败界面边框设计


【超详细C语言】带你吃透贪吃蛇游戏之精髓


游戏边框失败界面分析:


【超详细C语言】带你吃透贪吃蛇游戏之精髓


参考源代码:

//游戏失败界面边框void failGameUi(void){ int i;
system("cls");
//显示游戏失败提示 setColor(12); gotoXY(44, 3); printf("游 戏 失 败!!!");
setColor(11); gotoXY(17, 5);
//绘制上边框 printf("+----------------------------------------------------------------+");
//绘制下边框 gotoXY(17, 20); printf("+----------------------------------------------------------------+");
//绘制左右边框 for (i = 6; i < 20; i++) { gotoXY(17, i); printf("|");
gotoXY(82, i); printf("|"); }}


在moveKeyControl函数中按下ESC选项中添加如下代码:

//按下ESC键 结束游戏if (GetAsyncKeyState(VK_ESCAPE)){ endStatus = 3; failGameUi(); break;}


7.2 撞墙失败界面

显示效果如下:


【超详细C语言】带你吃透贪吃蛇游戏之精髓


界面分析:


【超详细C语言】带你吃透贪吃蛇游戏之精髓


参考代码:

//结束游戏int endGame(void){ int n; int highScore;
//显示游戏失败边框 failGameUi();
setColor(12);
//根据不同的状态显示不同的失败提示 switch (endStatus) { //撞到墙 case 1: gotoXY(38, 9); printf("您撞到墙了,游戏结束!!!"); break;
//咬到自己 case 2: break;
//用户按下ESC退出 case 3: break;
default: ; }
//显示您的得分 gotoXY(43, 12); setColor(13); printf("您的得分: %d", score);

//从文件中读取最高分 highScore = readFile();
if (score > highScore) { setColor(10); gotoXY(38, 16); printf("恭喜你, 你已经创记录了,"); //写文件 //writeFile(score); } else { setColor(10); gotoXY(38, 16); printf("加油哦,离最高分还差%d分", highScore - score); }
return 0;}


7.3 咬到蛇身失败界面

显示效果如下:


【超详细C语言】带你吃透贪吃蛇游戏之精髓


在endGame函数中修改代码如下:

//结束游戏int endGame(void){ int n; int highScore;
//显示游戏失败边框 failGameUi();
setColor(12); gotoXY(38, 9);
//根据不同的状态显示不同的失败提示 switch (endStatus) { //撞到墙 case 1: printf("您撞到墙了,游戏结束!!!"); break;
//咬到自己 case 2: printf("您咬到蛇身了,游戏结束!"); break;
//用户按下ESC退出 case 3: break;
default: ; }
//显示您的得分 gotoXY(43, 12); setColor(13); printf("您的得分: %d", score);

//从文件中读取最高分 highScore = readFile();
if (score > highScore) { setColor(10); gotoXY(38, 16); printf("恭喜你, 你已经创记录了,"); //写文件 //writeFile(score); } else { setColor(10); gotoXY(38, 16); printf("加油哦,离最高分还差%d分", highScore - score); }
return 0;}


7.4 ESC结束游戏界面

显示效果:


【超详细C语言】带你吃透贪吃蛇游戏之精髓


在endGame函数中修改代码如下:

//结束游戏int endGame(void){ int n; int highScore;
//显示游戏失败边框 failGameUi();
setColor(12); gotoXY(38, 9);
//根据不同的状态显示不同的失败提示 switch (endStatus) { //撞到墙 case 1: printf("您撞到墙了,游戏结束!!!"); break;
//咬到自己 case 2: printf("您咬到蛇身了,游戏结束!"); break;
//用户按下ESC退出 case 3: printf("您已经结束了游戏,游戏结束"); break;
default: ; }
//显示您的得分 gotoXY(43, 12); setColor(13); printf("您的得分: %d", score);

//从文件中读取最高分 highScore = readFile();
if (score > highScore) { setColor(10); gotoXY(38, 16); printf("恭喜你, 你已经创记录了,"); //写文件 //writeFile(score); } else { setColor(10); gotoXY(38, 16); printf("加油哦,离最高分还差%d分", highScore - score); }
return 0;}


7.5 界面添加选择

显示效果如下:


【超详细C语言】带你吃透贪吃蛇游戏之精髓


界面分析:


【超详细C语言】带你吃透贪吃蛇游戏之精髓


代码实现:

//结束游戏int endGame(void){ int n; int highScore;
while (1) { //显示游戏失败边框 failGameUi();
setColor(12); gotoXY(38, 9);
//根据不同的状态显示不同的失败提示 switch (endStatus) { //撞到墙 case 1: printf("您撞到墙了,游戏结束!!!"); break;
//咬到自己 case 2: printf("您咬到蛇身了,游戏结束!"); break;
//用户按下ESC退出 case 3: printf("您已经结束了游戏,游戏结束"); break;
default: ; }
//显示您的得分 gotoXY(43, 12); setColor(13); printf("您的得分: %d", score);

//从文件中读取最高分 highScore = readFile();
if (score > highScore) { setColor(10); gotoXY(38, 16); printf("恭喜你, 你已经创记录了,"); //写文件 //writeFile(score); } else { setColor(10); gotoXY(38, 16); printf("加油哦,离最高分还差%d分", highScore - score); }
//输出用户选择信息 gotoXY(25, 23); setColor(12); printf("在玩一局请输入: 1");
gotoXY(52, 23); printf("直接退出请输入:2");
gotoXY(46, 25); setColor(11); printf("请选择:");
scanf("%d", &n); getchar();
if (1 == n) { score = 0; sleepTime = 350; add = 1; break; } else if (2 == n) { exit(0); } else { gotoXY(30, 27); setColor(12); printf("您的输入有误, 请重新输入, 按下任意键继续"); getchar(); } } return 0;}


7.6 写文件实现

//写文件int writeFile(int score){ FILE *fp = NULL;
fp = fopen("save.txt", "w+");
fprintf(fp, "%d", score);
fclose(fp);
return 0;}


在endGame函数中,如果破纪录了就写文件

if (score > highScore){ setColor(10); gotoXY(38, 16); printf("恭喜你, 你已经创记录了,"); //写文件 writeFile(score);}


08. 一起来找茬

//销毁蛇int destroySnake(void){ snake_t *tmp = NULL; snake_t *save = NULL;
tmp = head; while (NULL != tmp) { save = tmp->next; free(tmp); tmp = save; }
head = NULL;
return 0;}


09. 项目扩展

  • 设置关卡

    蛇移动速度

  • 保存每一个用户的得分信息

  • 排名榜


10. 项目总结

基础知识:C语言 数据结构中简单单向链表


【超详细C语言】带你吃透贪吃蛇游戏之精髓

说个题外话,鸟哥是个比较喜欢折腾的程序员,业余喜欢开发自己网站、小程序、App等,这些东西统统离不开服务器!最近就围绕服务器的主题创建了一个微信群,喜欢玩服务器或者想自己开发一款产品的读者可以进来,相互学习交流!我也会时不时的带大家撸点和服务器相关的优惠券!不感兴趣,不喜欢折腾的就没必要凑着闹了!


发送【服务器】即可获取邀请链接

这是我部署的机器人,请勿调戏!


推荐阅读




以上是关于超详细C语言带你吃透贪吃蛇游戏之精髓的主要内容,如果未能解决你的问题,请参考以下文章

C语言之贪吃蛇(ncurses)

C语言项目贪吃蛇游戏(下)

100行Python代码实现贪吃蛇小游戏(超详细)

贪吃蛇游戏改运行背景颜色的C语言代码。

C语言项目:贪吃蛇游戏(双人模式),详细思路+源码分享

c语言 贪吃蛇 程序