超详细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. 项目总结
01. 开发背景
贪吃蛇起源于西方,来自于蛇骗夏娃和亚当偷吃禁果的神话。人们为了说明蛇的一个“贪”字,开发出了贪吃蛇游戏。本公开课使用C语言开发一个贪吃蛇游戏。
贪吃蛇最初为人们所知的是诺基亚手机附带的一个小游戏,它伴随着诺基亚手机走向世界。现在的贪吃蛇出现了许多衍生版本,并被移植到各种平台上。
通过本案例的学习,大家可以学到:
Visual Studio 2017开发环境
C语言中的三大结构和函数
C语言中动态内存申请和释放
C语言中文件基本操作
C语言中的简单单向链表
控制终端基本设置和监听按键
C语言简单游戏开发流程
C语言简单游戏开发调试技巧
02. 功能介绍
贪吃蛇的游戏规则也很简单,具体为:蛇出现在封闭的空间中,同时在地图上会随机出现食物,玩家通过键盘上的上下左右方向键来控制蛇的前进方向。蛇头撞到食物,则食物消失,表示被蛇吃掉了,蛇身增加一节,增加玩家的得分。接着又随机出现一个食物,等待蛇来吃。如果蛇在前进的过程中撞到墙或者咬到蛇身或者玩家按下ESC键,则游戏退出。
项目演示
03. 欢迎界面设计
欢迎界面如下:
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;
}
十进制颜色对照表:
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;
}
测试效果如下:
3.5 欢迎界面函数
界面设计分析:
参考代码:
//欢迎界面
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. 游戏帮助界面设计
游戏说明模块如下:
游戏帮助界面参考代码:
//游戏帮助界面
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 游戏失败界面边框设计
游戏边框失败界面分析:
参考源代码:
//游戏失败界面边框
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 撞墙失败界面
显示效果如下:
界面分析:
参考代码:
//结束游戏
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 咬到蛇身失败界面
显示效果如下:
在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结束游戏界面
显示效果:
在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 界面添加选择
显示效果如下:
界面分析:
代码实现:
//结束游戏
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语言 数据结构中简单单向链表
说个题外话,鸟哥是个比较喜欢折腾的程序员,业余喜欢开发自己网站、小程序、App等,这些东西统统离不开服务器!最近就围绕服务器的主题创建了一个微信群,喜欢玩服务器或者想自己开发一款产品的读者可以进来,相互学习交流!我也会时不时的带大家撸点和服务器相关的优惠券!不感兴趣,不喜欢折腾的就没必要凑着闹了!
发送【服务器】即可获取邀请链接
这是我部署的机器人,请勿调戏!
推荐阅读
以上是关于超详细C语言带你吃透贪吃蛇游戏之精髓的主要内容,如果未能解决你的问题,请参考以下文章