C语言实现贪吃蛇游戏

文章目录

  • 前言
  • 一、蛇的结构的创建
  • 二、游戏测试的逻辑
  • 三、初始化游戏
  • 四、游戏运行
  • 五、游戏结束
  • 总结


前言

C语言实现贪吃蛇游戏


一、蛇的结构的创建

  • 先创建一个蛇身的节点
  • 在创建蛇的结构(包括:指向蛇头的指针,指向食物的指针,游戏的状态,蛇的速度,蛇的方向,食物的分数,总得分)

蛇的方向和游戏的状态采用枚举列举。

// 蛇的方向
enum DIRECTION
{UP = 1,DOWN,LEFT,RIGHT
};// 游戏的状态(正常、撞墙、撞到自己、正常退出)
enum GAME_STATUS
{ok,//正常状态KILL_BY_WALL,// 撞墙死KILL_BY_SELF,// 撞到自己死END_NORMAL // esc正常退出
};// 创建蛇身的节点
typedef struct SnakeNode 
{// 每个节点坐标int x;int y;// 写一个蛇身节点的地址struct SnakeNode* next;
}SnakeNode, *pSnakeNode;// 真正的贪吃蛇
typedef struct Snake
{pSnakeNode _pSnake;// 指向蛇头的指针pSnakeNode _pFood; // 指向食物节点的指针enum DIRECTION _dir; // 蛇的方向enum GAME_STATUS _status;// 当前游戏的状态int _food_weight; // 一个食物的分数int _score; // 总分数int _sleep_time; // 休眠时间,时间越长,速度越慢,时间越短,速度越快
}Snake, *pSnake;

二、游戏测试的逻辑

  • 每次游戏开始都先清空屏幕
  • 初始化游戏
  • 游戏运行
  • 游戏结束
void test()
{int ch = 0;do{system("cls");// 创建贪吃蛇Snake snake = { 0 };// 初始化游戏// 1. 打印欢迎界面// 2. 打印功能介绍// 3. 绘制地图// 4. 创建蛇// 5. 创建食物// 6. 设置游戏的相关信息GameStart(&snake);// 游戏运行GameRun(&snake);// 游戏结束--- 游戏的善后工作GameEnd(&snake);SetPos(25, 18);printf("要再来一局吗?(Y/N)");ch = getchar();while (getchar() != '\n');} while (ch == 'Y' || ch == 'y');SetPos(0, 27);
}

三、初始化游戏

  • 打印欢迎界面
  • 打印功能介绍
  • 绘制地图
  • 创建蛇
  • 创建食物
  • 在创建蛇和创建食物同时初始化蛇的基本信息
void SetPos(short x, short y)
{// 获得标准输出设备的句柄HANDLE houtput = NULL;houtput = GetStdHandle(STD_OUTPUT_HANDLE);//定位光标的位置COORD pos = { x, y };SetConsoleCursorPosition(houtput, pos);
}// 1-2.欢迎界面的打印及功能介绍函数
void WelcomeToGame()
{SetPos(40, 14);wprintf(L"欢迎来到贪吃蛇小游戏!!\n");SetPos(42, 25);system("pause");system("cls");SetPos(30, 14);wprintf(L"按↑. ↓. ←. →来控制蛇的方向,按F3加速,F4减速");SetPos(40, 16);wprintf(L"加速可以得到跟高的分数");SetPos(42, 25);system("pause");system("cls");}// 3. 打印地图
void CreateMap()
{// 上int i = 0;for (i = 0; i < 29; i++){wprintf(L"%lc", WALL);}// 下SetPos(0, 26);for (i = 0; i < 29; i++){wprintf(L"%lc", WALL);}// 左for (i = 1; i <= 25; i++){SetPos(0, i);wprintf(L"%lc", WALL);}// 右for (i = 1; i <= 25; i++){SetPos(56, i);wprintf(L"%lc", WALL);}
}// 4. 创建蛇
void InitSnake(pSnake ps)
{pSnakeNode cur = NULL;int i = 0;for (i = 0; i < 5; i++){// 申请一个蛇身节点cur = (pSnakeNode)malloc(sizeof(SnakeNode));if (NULL == cur){perror("InitSnake()::malloc()");return;}cur->next = NULL;cur->x = POS_X + 2 * i;cur->y = POS_Y;// 头插法插入链表if (ps->_pSnake == NULL) // 空链表{ps->_pSnake = cur;}else // 非空链表{cur->next = ps->_pSnake;ps->_pSnake = cur;}}// 打印蛇身cur = ps->_pSnake;SetPos(cur->x, cur->y);wprintf(L"%lc", HEAD);cur = cur->next;while (cur){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}// 设置贪吃蛇属性ps->_dir = RIGHT; // 初始方向设置为向右ps->_score = 0; // 总成绩初始为0ps->_food_weight = 10;// 一个食物10分ps->_sleep_time = 200; // 休眠时间,单位为毫秒ps->_status = ok; // 默认游戏状态ok}// 5. 创建食物函数
void CreateFood(pSnake ps)
{int x = 0;int y = 0;
again:// 随机生成食物位置,不能在墙体上do{x = rand() % 53 + 2;y = rand() % 25 + 1;} while (x % 2 != 0);// 随机生成的食物也不能在蛇身上pSnakeNode cur = ps->_pSnake;while (cur){if (x == cur->x && y == cur->y){goto again;}cur = cur->next;}// 申请一个食物节点pSnakeNode pFood = malloc(sizeof(SnakeNode));if (pFood == NULL){perror("CreateFood()::malloc()");return;}pFood->next = NULL;pFood->x = x;pFood->y = y;// 定位位置打印食物SetPos(pFood->x, pFood->y);wprintf(L"%lc", FOOD);ps->_pFood = pFood;}// 初始化游戏
void GameStart(pSnake ps)
{// 0. 先设置窗口大小再光标隐藏//设置窗口大小system("mode con cols=100 lines=30");system("title 贪吃蛇");// 获得标准输出设备的句柄HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);// 隐藏光标操作CONSOLE_CURSOR_INFO CursorInfo;GetConsoleCursorInfo(houtput, &CursorInfo);// 获取控制台光标信息CursorInfo.bVisible = false; // 隐藏控制台光标SetConsoleCursorInfo(houtput, &CursorInfo);// 设置控制台光标信息// 1. 打印欢迎界面// 2. 打印功能介绍WelcomeToGame();// 3. 绘制地图CreateMap();// 4. 创建蛇InitSnake(ps);// 5. 创建食物CreateFood(ps);
}

四、游戏运行

  • 游戏运行主要包括
  • 打印帮助信息
  • 按键的检测(改变方向)
  • 暂停游戏功能
  • 判断下一个节点是否为食物(吃掉食物、没有食物)
  • 检测是否撞墙
  • 检测是否撞到自己
// 打印帮助信息函数
void PrintHelpInfo()
{SetPos(64, 17);wprintf(L"不能穿墙,不能咬到自己");SetPos(64, 18);wprintf(L"按↑. ↓. ←. →来控制蛇的方向");SetPos(64, 19);wprintf(L"+ 为加速,- 为减速");SetPos(64, 20);wprintf(L"ESC: 退出游戏!SPACE: 暂停游戏");SetPos(64, 22);wprintf(L"hhb@版权");
}// 检测按键的宏
#define KEY_PRESS(vk) ((GetAsyncKeyState(vk) & 1)? 1 : 0)// 暂停函数
void Pause()
{while (1){Sleep(200);if (KEY_PRESS(VK_SPACE)){break;}}}// 判断下一个节点是否为食物
int NextIsFood(pSnakeNode pn, pSnake ps)
{return (pn->x == ps->_pFood->x && pn->y == ps->_pFood->y);
}// 吃掉食物函数
void EatFood(pSnakeNode pn, pSnake ps)
{// 将食物节点头插到蛇头之前ps->_pFood->next = ps->_pSnake;ps->_pSnake = ps->_pFood;// 释放next节点free(pn);pn = NULL;// 打印蛇身pSnakeNode cur = ps->_pSnake;SetPos(cur->x, cur->y);wprintf(L"%lc", HEAD);cur = cur->next;while (cur){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}ps->_score += ps->_food_weight;// 吃掉食物,再创建一个新的事物CreateFood(ps);}// 没有食物
void NoFood(pSnakeNode pn, pSnake ps)
{// 新的节点头插到链表中pn->next = ps->_pSnake;ps->_pSnake = pn;// 打印蛇pSnakeNode cur = ps->_pSnake;SetPos(cur->x, cur->y);wprintf(L"%lc", HEAD);cur = cur->next;while (cur->next->next != NULL){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}// 将最后一个节点打印成空白SetPos(cur->next->x, cur->next->y);printf("  ");// 释放最后一个节点free(cur->next);cur->next = NULL;
}// 检测蛇是否撞墙
void KillByWall(pSnake ps)
{if (ps->_pSnake->x == 0 || ps->_pSnake->x == 56 ||ps->_pSnake->y == 0 || ps->_pSnake->y == 26){ps->_status = KILL_BY_WALL;}
}// 检测蛇是否撞到自己
void KillBySelf(pSnake ps)
{pSnakeNode cur = ps->_pSnake->next;while (cur){if (cur->x == ps->_pSnake->x && cur->y == ps->_pSnake->y){ps->_status = KILL_BY_SELF;break;}cur = cur->next;}
}// 蛇向前走一步函数
void SnakeMove(pSnake ps)
{// 创建下一个位置的节点pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));if (pNextNode == NULL){perror("SnakeMove()::malloc()");return;}// 确定下一节点的位置switch (ps->_dir){case UP:pNextNode->x = ps->_pSnake->x;pNextNode->y = ps->_pSnake->y - 1;break;case DOWN:pNextNode->x = ps->_pSnake->x;pNextNode->y = ps->_pSnake->y + 1;break;case LEFT:pNextNode->x = ps->_pSnake->x - 2;pNextNode->y = ps->_pSnake->y;break;case  RIGHT:pNextNode->x = ps->_pSnake->x + 2;pNextNode->y = ps->_pSnake->y;break;}// 需要判断下一点是否是食物if (NextIsFood(pNextNode, ps)){EatFood(pNextNode, ps);}else{NoFood(pNextNode, ps);}// 检测蛇是否撞到墙KillByWall(ps);// 检测蛇是否撞到自己KillBySelf(ps);
}// 游戏运行
void GameRun(pSnake ps)
{// 打印帮助信息PrintHelpInfo();do{// 打印总得分和食物权重SetPos(64, 10);wprintf(L"总得分为: %d", ps->_score);SetPos(64, 12);wprintf(L"当前食物的分数为: %2d", ps->_food_weight);// 检测按键if (KEY_PRESS(VK_UP)&& ps->_dir != DOWN){ps->_dir = UP;}else if (KEY_PRESS(VK_DOWN)&& ps->_dir != UP){ps->_dir = DOWN;}else if (KEY_PRESS(VK_LEFT) && ps->_dir != RIGHT){ps->_dir = LEFT;}else if (KEY_PRESS(VK_RIGHT) && ps->_dir != LEFT){ps->_dir = RIGHT;}else if (KEY_PRESS(VK_SPACE)){// 暂停Pause();}else if (KEY_PRESS(VK_ESCAPE)){// 正常退出ps->_status = END_NORMAL;}else if (KEY_PRESS(VK_ADD)){// 加速if (ps->_sleep_time > 80){ps->_sleep_time -= 30;ps->_food_weight += 2;}}else if (KEY_PRESS(VK_SUBTRACT)){// 减速if (ps->_food_weight >2 ){ps->_sleep_time += 30;ps->_food_weight -= 2;}}// 蛇向前走走一步SnakeMove(ps);// 蛇每走一步sleep一下Sleep(ps->_sleep_time);} while (ps->_status == ok);}

五、游戏结束

  • 根据蛇结构中游戏的状态打印对应的信息,并退出
  • 销毁链表
  • 在测试函数中循环执行,并增加提示信息,是否再来一把。
// 游戏结束--游戏善后工作
void GameEnd(pSnake ps)
{SetPos(24, 12);switch (ps->_status){case END_NORMAL:wprintf(L"您正常退出了!!\n");break;case KILL_BY_WALL:wprintf(L"您撞到墙上了,游戏结束!!\n");break;case KILL_BY_SELF:wprintf(L"您撞到自己了,游戏结束!!\n");break;}// 销毁链表pSnakeNode cur = ps->_pSnake;while (cur){pSnakeNode del = cur;cur = cur->next;free(del);}
}

《点击查看源码》


总结

C语言实现贪吃蛇游戏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/13887.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初识DataX3.0

目前接到任务&#xff0c;让同步表数据。市面很多同步工具不一一尝试了&#xff0c;信赖阿里&#xff0c;所以调研了一下阿里的dataX,一点点来吧&#xff0c;学习为主 环境准备&#xff1a;linux6.8 python自带的2.7 MySQL 5.7.1 1.先下载&#xff1a; wget http://datax-o…

油猴脚本使用cookie一般是某请求返回的setcookie,一般不是js生成的,直接请求拼接

写完hook脚本 删除页面cooike&#xff0c;打开开发者模式&#xff0c;刷新页面 cookie一般是某请求返回的setcookie,一般不是js生成的&#xff0c;直接请求拼接带cookie请求 看网络里的cookie httponly打钩的是服务器返回的&#xff0c;但不一定对&#xff0c;还是要看保存日…

MPLS VPN

不是公司的产品&#xff0c;是运营商对外提供的一种服务 没咋懂&#xff0c;oh my god

安防监控视频平台EasyNVR级联视频上云系统EasyNVS出现“Login error”报错的原因排查

EasyNVR安防视频云平台是旭帆科技TSINGSEE青犀旗下支持RTSP/Onvif协议接入的安防监控流媒体视频云平台。平台具备视频实时监控直播、云端录像、云存储、录像检索与回看、告警等视频能力&#xff0c;能对接入的视频流进行处理与多端分发&#xff0c;包括RTSP、RTMP、HTTP-FLV、W…

Milvus的执行引擎Knowhere

前言 本文将会介绍Knowhere这个概念&#xff0c;它是milvus向量执行引擎的核心。 概览 Knowhere是milvus向量咨询引擎的核心&#xff0c;它将好几个向量相似搜索库聚集在一起&#xff08;包括faiss、hnswlib、annoy&#xff09;。Knowhere也被设计支持异构计算。它控制在什么…

Java设计模式-观察者模式(19)

Java中的观察者模式(Observer Pattern)是一种行为设计模式,它定义了对象之间的一对多依赖关系,这样一来,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。观察者模式使得你可以独立地改变目标和观察者,让两者之间的耦合度降低。 基本组成部分 …

电商平台api接口:采购比价可用的比价工具推荐

电商平台api接口 目前&#xff0c;许多企业在进行内部采购时都有比价的需求。企业利用比价采购这一方式&#xff0c;能通过对比不同平台上、不同供应商的报价&#xff0c;进而选择最符合其需求和预算的产品或服务。 在比价采购的流程中&#xff0c;最重要的步骤就是企业在明确…

C#Csharp,SharpPcap网络抓包程序及源码(适合网络分析直接使用或源码二次开发)

目录 1.程序简介2.程序截图3.程序源码 1.程序简介 C#Csharp,SharpPcap网络抓包程序及源码&#xff08;适合网络分析直接使用或源码二次开发&#xff09; 2.程序截图 3.程序源码 https://download.csdn.net/download/xzzteach/89325817

Linux学习(十四)-- 软件安装:yum命令、apt命令

目录 1. yum命令&#xff1a;基于RPM的软件包管理器 2. apt命令&#xff1a;在 Debian 和 Ubuntu 中的 Shell 前端软件包管理器 apt 常用命令 1. yum命令&#xff1a;基于RPM的软件包管理器 yum命令来自英文词组yellow dog updater modified的缩写。 其功能&#xff1a; 在L…

沃创云外呼系统——能够企业带来什么样的帮助

沃创云外呼系统是一款功能强大的呼叫系统&#xff0c;能够助力企业提升营销效率&#xff0c;实现业绩增长。以下是沃创云外呼系统具体可以为企业带来的帮助 01节约成本 沃创云外呼系统能够自动拨打海量客户电话号码&#xff0c;降低企业成本&#xff0c;提高工作效率。使用沃创…

1.golang背景、特点介绍

背景介绍 Go 是 Google 开发的一种编程语言。 它于 2009 年由 Robert Griesemer、Rob Pike 和 Ken Thompson 作为开源项目发布。 从那时起&#xff0c;Go 语言就被用于开发其他众所周知的技术&#xff0c;如 Docker、Kubernetes 和 Terraform。 尽管 Go 语言在服务器端和云软件…

EI会议论文的格式和模板在哪里可以找到?

要找到EI会议论文的格式和模板&#xff0c;首先访问会议的官方网站&#xff0c;这是最直接的途径。会议网站通常在下载中心或投稿指南中提供详细的模板和格式要求。此外&#xff0c;你也可以查阅会议通知邮件、合作出版社平台、往届会议论文&#xff0c;或者直接联系会议组织者…

go语言中的一个特别的语法 //go:embed 可将将静态文件内容读取到string, []byte和 embed.FS 变量并直接打包到exe包中

go语言中的一个特别的语法 //go:embed 看上去像是注释&#xff0c;实则是golang中的一个内置的语法&#xff0c;而且是仅在你的go代码编译时生效的语法&#xff0c; 借助他我们可以将我们的静态资源文件读取到FS直接打包到我们的exe执行文件中。 同时他还支持文件的模式匹配…

计算机网络学习小结_数据链路层

数据链路和帧 帧&#xff1a;数据链路层传输基本单元。链路层将网络层传过来的数据构成帧发到链路上&#xff0c;并将发到链路层的帧取出数据交给网络层 数据报/分组/包&#xff1a;网络层传输基本单元 三个基本问题 即封装成帧、透明传输、差错检测 封装成帧 概念&#…

Docker Portainer使用

Portainer是什么 Docker Portainer是一个轻量级的 Web UI 管理界面,可以用来管理Docker环境。它提供了一个直观的控制台,用户可以通过它来管理Docker主机、容器、网络、卷等Docker资源。 Portainer的主要功能和特点包括: 容器管理:可以查看、启动、停止、删除容器,以及查看容器…

正确解决pymysql.err.InternalError:(1049, Unknown error 1049)异常的有效解决方法

pymysql.err.InternalError: &#xff08;1049&#xff0c;Unknown error 1049&#xff09;这个异常通常表示客户端尝试连接到MySQL或 MariaDB服务器时出现了问题。错误代码 1049通常与数据库服务未运行、连接参数错误或数据库不存在有关。 为了解决这个问题&#xff0c;您…

对比解读国际R155法规和GB整车强标要求的差异性

附&#xff1a;汽车整车信息安全技术要求和R155法规文档&#xff0c;文末下载 在早期的汽车软件设计中&#xff0c;汽车本身很少与外界互联&#xff0c;并没有考虑太多的安全性。而随着电子电气架构的发展&#xff0c;大量的软件控制取代了机械控制&#xff0c;带来了ADAS、OT…

VSCODE调试C++(本人是openfoam求解器)时无法显示Vector,map等容器的值

一维数组&#xff1a; 可以在watch内添加表达式&#xff1a;*(type(*)[size])vectorName 例如&#xff1a;想查看vector<int> nums(6), 可以添加*(int(*)[6])nums。 上面是一维数组情况&#xff1a; ((double (*)[1000])&U[1000]) 表示从下标1000开始访问1000-200…

C++实现童年游戏

其中多处坐标的代码是经过运算移项推导出的 #include<easyx.h> #include<conio.h> #include<time.h> #include<stdio.h> bool Timer(int id, int ms)//计时器&#xff0c;过了多少毫秒就会返回真 {static long start[3] { 0 };long last clock();if…

关于linux的防护,以及群集你要知道的有哪些11-搭建Zabbix监控系统

1、zabbix具备功能 主机的性能监控、网络设备性能监控、数据库性能监控、多种警告方式、详细报表图表绘制 2、zabbix的监测对象 Linux服务器、Windows服务器、路由器、交换机等网络设备 3、zabbix的监控架构 server-client架构&#xff1a;适用于网络比较简单&#xff0c…