当前位置: 首页 > news >正文

C语言之实现贪吃蛇小游戏篇(2)

目录

🎇测试游戏test.c

🎇游戏头文件包含&函数声明snake.h

🎇游戏实现snake.c


🎇测试游戏test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "snake.h"
void test()
{int ch = 0;do{Snake snake = { 0 };//创建了贪吃蛇//1. 游戏开始 - 初始化游戏GameStart(&snake);//2. 游戏运行 - 游戏的正常运行过程GameRun(&snake);//3. 游戏结束 - 游戏善后(释放资源)GameEnd(&snake);SetPos(20, 18);printf("再来一局吗?(Y/N):");ch = getchar();getchar();// 清理掉\n} while (ch == 'Y' || ch == 'y');SetPos(0, 27);
}
int main()
{//设置程序适应本地环境setlocale(LC_ALL, "");srand((unsigned int)time(NULL));test();return 0;
}

🎇游戏头文件包含&函数声明snake.h

#pragma once
#include <locale.h>
#include <stdlib.h>
#include <windows.h>
#include <stdbool.h>
#include <stdio.h>
#include <time.h>#define WALL L'□'
#define BODY L'●'
#define FOOD L'★'#define POS_X 24
#define POS_Y 5#define KEY_PRESS(VK)  ( (GetAsyncKeyState(VK) & 0x1) ? 1 : 0 )enum DIRECTION
{UP = 1,DOWN,LEFT,RIGHT
};enum GAME_STATUS
{OK,//正常运行END_NORMAL,//按ESC退出KILL_BY_WALL,KILL_BY_SELF
};//贪吃蛇结点的描述
typedef struct SnakeNode
{//坐标int x;int y;struct SnakeNode* next;
}SnakeNode, * pSnakeNode;//贪吃蛇的结构
typedef struct Snake
{pSnakeNode _pSnake;//指向贪吃蛇头结点的指针pSnakeNode _pFood;//指向食物结点的指针int _Score;//贪吃蛇累计的总分int _FoodWeight;//一个食物的分数int _SleepTime;//每走一步休息的时间,时间越短,速度越快,时间越长,速度越慢enum DIRECTION _Dir;//描述蛇的方向enum GAME_STATUS _Status;//游戏的状态:正常、退出、撞墙、吃到自己
}Snake, * pSnake;//游戏开始 - 完成游戏的初始化动作
void GameStart(pSnake ps);//定位坐标
void SetPos(short x, short y);//游戏开始的欢迎界面
void WelComeToGame();//打印地图
void CreateMap();//初始化贪吃蛇
void InitSnake(pSnake ps);//创建食物
void CreateFood(pSnake ps);//游戏的正常运行
void GameRun(pSnake ps);//打印帮助信息
void PrintHelpInfo();//游戏暂定和恢复
void Pause();//蛇的移动
void SnakeMove(pSnake ps);//判断蛇头到达的坐标处是否是食物
int NextIsFood(pSnake ps, pSnakeNode pnext);//吃掉食物
void EatFood(pSnake ps, pSnakeNode pnext);//不吃食物
void NoFood(pSnake ps, pSnakeNode pnext);//蛇是否撞墙
void KillByWall(pSnake ps);//蛇是否自杀
void KillBySelf(pSnake ps);//游戏结束后的善后处理
void GameEnd(pSnake ps);

🎇游戏实现snake.c

#define _CRT_SECURE_NO_WARNINGS 1#include "snake.h"//设置光标的坐标
void SetPos(short x, short y)
{COORD pos = { x, y };HANDLE hOutput = NULL;//获取标准输出的句柄(用来标识不同设备的数值)hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//设置标准输出上光标的位置为posSetConsoleCursorPosition(hOutput, pos);
}//打印欢迎界面
void WelComeToGame()
{//定位光标SetPos(40, 14);printf("欢迎来到贪吃蛇小游戏");SetPos(40, 25);system("pause");//pause是暂停system("cls");SetPos(20, 14);printf("使用 ↑ . ↓ . ← . → . 分别控制蛇的移动, F3是加速,F4是减速");SetPos(40, 25);system("pause");system("cls");
}//创建墙体
void CreateMap()
{//上SetPos(0, 0);int i = 0;for (i = 0; i <= 56; i += 2){wprintf(L"%lc", WALL);}//下SetPos(0, 26);for (i = 0; i <= 56; i += 2){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);}
}//初始化蛇
void InitSnake(pSnake ps)
{pSnakeNode cur = NULL;int i = 0;for (i = 0; i < 5; i++){cur = (pSnakeNode)malloc(sizeof(SnakeNode));if (cur == NULL){perror("InitSnake()::malloc()");return;}cur->x = POS_X + 2 * i;cur->y = POS_Y;cur->next = NULL;//头插法if (ps->_pSnake == NULL){ps->_pSnake = cur;}else{cur->next = ps->_pSnake;ps->_pSnake = cur;}}//打印蛇身cur = ps->_pSnake;while (cur){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}ps->_Status = OK;ps->_Score = 0;ps->_pFood = NULL;ps->_SleepTime = 200;ps->_FoodWeight = 10;ps->_Dir = RIGHT;
}//创建食物
void CreateFood(pSnake ps)
{int x = 0;int y = 0;
again:do{x = rand() % 53 + 2;y = rand() % 25 + 1;} while (x % 2 != 0);//x坐标必须是2的倍数//坐标不能和蛇的身体冲突pSnakeNode cur = ps->_pSnake;while (cur){//比较坐标if (cur->x == x && cur->y == y){goto again;}cur = cur->next;}pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));if (pFood == NULL){perror("CreateFood()::malloc()");return;}pFood->x = x;pFood->y = y;ps->_pFood = pFood;//打印食物SetPos(x, y);wprintf(L"%lc", FOOD);
}//游戏开始
void GameStart(pSnake ps)
{//控制台窗口的设置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);//设置控制台光标状态//打印欢迎界面WelComeToGame();//创建地图CreateMap();//初始化贪食蛇InitSnake(ps);//创建食物CreateFood(ps);
}//打印帮助信息
void PrintHelpInfo()
{SetPos(64, 15);printf("1.不能撞墙,不能咬到自己");SetPos(64, 16);printf("2.使用 ↑.↓.←.→ 分别控制蛇的移动");SetPos(64, 17);printf("3.F3加速,F4减速");SetPos(64, 18);printf("4.ESC-退出, 空格-暂停游戏");SetPos(64, 20);printf("@TSQ");
}//休眠
void Pause()
{while (1){Sleep(100);if (KEY_PRESS(VK_SPACE)){break;}}
}//下个节点
int NextIsFood(pSnake ps, pSnakeNode pnext)
{if (ps->_pFood->x == pnext->x && ps->_pFood->y == pnext->y){return 1;}else{return 0;}
}//吃掉食物
void EatFood(pSnake ps, pSnakeNode pnext)
{//头插pnext->next = ps->_pSnake;ps->_pSnake = pnext;//打印蛇pSnakeNode cur = ps->_pSnake;while (cur){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}free(ps->_pFood);ps->_Score += ps->_FoodWeight;CreateFood(ps);//新创建食物
}//不吃食物
void NoFood(pSnake ps, pSnakeNode pnext)
{//头插pnext->next = ps->_pSnake;ps->_pSnake = pnext;//打印蛇身pSnakeNode cur = ps->_pSnake;while (cur->next->next){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 (ps->_pSnake->x == cur->x && ps->_pSnake->y == cur->y){ps->_Status = KILL_BY_SELF;}cur = cur->next;}
}//🐍蛇移动
void SnakeMove(pSnake ps)
{pSnakeNode pNext = (pSnakeNode)malloc(sizeof(SnakeNode));if (pNext == NULL){perror("SnakeMove()::malloc()");return;}pNext->next = NULL;switch (ps->_Dir){case UP:pNext->x = ps->_pSnake->x;pNext->y = ps->_pSnake->y - 1;break;case DOWN:pNext->x = ps->_pSnake->x;pNext->y = ps->_pSnake->y + 1;break;case LEFT:pNext->x = ps->_pSnake->x - 2;pNext->y = ps->_pSnake->y;break;case RIGHT:pNext->x = ps->_pSnake->x + 2;pNext->y = ps->_pSnake->y;break;}//判断蛇头到达的坐标处是否是食物if (NextIsFood(ps, pNext)){//吃掉食物EatFood(ps, pNext);}else{//不吃食物NoFood(ps, pNext);}//蛇是否撞墙KillByWall(ps);//蛇是否自杀KillBySelf(ps);
}//游戏运行
void GameRun(pSnake ps)
{PrintHelpInfo();do{SetPos(64, 10);printf("得分:%05d", ps->_Score);SetPos(64, 11);printf("每个食物的分数:%2d", ps->_FoodWeight);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_ESCAPE)){ps->_Status = END_NORMAL;break;}else if (KEY_PRESS(VK_SPACE)){Pause();}else if (KEY_PRESS(VK_F3))//加速{if (ps->_SleepTime >= 80){ps->_SleepTime -= 30;ps->_FoodWeight += 2;}}else if (KEY_PRESS(VK_F4))//减速{if (ps->_SleepTime < 320){ps->_SleepTime += 30;ps->_FoodWeight -= 2;}}Sleep(ps->_SleepTime);SnakeMove(ps);} while (ps->_Status == OK);
}//游戏结束
void GameEnd(pSnake ps)
{SetPos(20, 12);switch (ps->_Status){case END_NORMAL:printf("您主动退出游戏\n");break;case KILL_BY_SELF:printf("自杀了,游戏结束\n");break;case KILL_BY_WALL:printf("撞墙了,游戏结束\n");break;}//释放蛇身的结点pSnakeNode cur = ps->_pSnake;while (cur){pSnakeNode del = cur;cur = cur->next;free(del);}ps->_pSnake = NULL;}

屏幕录制 2023-12-02 204515

 

✔✔✔✔✔最后感谢大家的阅读,若有错误和不足,欢迎指正!乖乖敲代码哦! 

代码---------→【唐棣棣 (TSQXG) - Gitee.com】

联系---------→【邮箱:2784139418@qq.com】

相关文章:

C语言之实现贪吃蛇小游戏篇(2)

目录 &#x1f387;测试游戏test.c &#x1f387;游戏头文件包含&函数声明snake.h &#x1f387;游戏实现snake.c &#x1f387;测试游戏test.c #define _CRT_SECURE_NO_WARNINGS 1 #include "snake.h" void test() {int ch 0;do{Snake snake { 0 };//创建…...

Comparator接口

Comparator接口 Comparator 是 Java 中用于比较对象的接口。它允许开发者实现自定义的比较逻辑&#xff0c;以用于对对象进行排序或者确定它们的顺序。 主要方法&#xff1a; Comparator 接口中包含一个抽象方法&#xff1a; int compare(T o1, T o2)&#xff1a;用于比较两…...

SELinux refpolicy详解(9)

接前一篇文章&#xff1a;SELinux refpolicy详解&#xff08;8&#xff09; 三、refpolicy内容详解 上一回讲解了refpolicy源码根目录下的build.conf文件的前一部分内容。本回继续讲解其后一部分。 2. build.conf 文件路径&#xff1a;refpolicy源码根目录/build.conf。 文…...

零基础上手,秒识别检测,IDEA研究院发布全新T-Rex模型

目标检测作为当前计算机视觉落地的热点技术之一&#xff0c;已被广泛应用于自动驾驶、智慧园区、工业检测和卫星遥感等场景。开发者在研究相关目标检测技术时&#xff0c;通常需熟练掌握图像目标检测框架&#xff0c;如通用目标检测框架 YOLO 系列&#xff0c;旋转目标检测框架…...

python每日一题——20旋转图像

题目 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]]…...

云计算生成式 -给你不一样的音乐推荐新体验

目录 摘要&#xff1a; 正文&#xff1a; 一、亚马逊云与生成式 AI 结合的展望/总结 二、我用亚马逊云科技生成式 AI 产品打造了什么&#xff0c;解决了什么问题 三、未来云端技术发展趋势的见解 四、云端技术未来需要解决的问题 1、如何保护数据安全和隐私&#xff1f; …...

Zabbix 6.0部署+自定义监控项+自动发现与自动注册+部署zabbix代理服务器

Zabbix 6.0 Zabbix 6.0一、关于zabbix1、什么是zabbix2、zabbix工作原理3、zabbix 6.0 特性4、zabbix 6.0 功能组件 二、Zabbix 6.0 部署1、 部署 zabbix 服务端(1) 部署 Nginx PHP 环境并测试(2) 部署数据库(3) 编译安装 zabbix server 服务端(4) 部署 Web 前端&#xff0c;进…...

Docker 简介及其常用命令详解

Docker 简介及其常用命令详解 Docker 自推出以来&#xff0c;已成为开发和运维领域的重要工具。它简化了应用的部署、测试和分发过程&#xff0c;使得容器化技术成为现代软件开发的标准实践。本文将为您提供Docker的基础介绍以及其常用命令的详细讲解。 什么是Docker&#xf…...

基于PHP的高中生物学习平台

有需要请加文章底部Q哦 可远程调试 基于PHP的高中生物学习平台 一 介绍 此高中生物学习平台基于原生PHP开发&#xff0c;数据库mysql。系统角色分为用户和管理员。(附带参考设计文档) 技术栈&#xff1a;phpmysqlphpstudyvscode 二 功能 学生 1 注册/登录/注销 2 个人中心 …...

Git多库多账号本地SSH连接配置方法

Git多库多账号本地SSH连接配置方法 一、前言二、环境三、帮助文档四、多环境配置4.1 配置config文件 五、生成RSA秘钥对5.1 ssh秘钥位置5.2 生成秘钥对&#xff08;公钥、私钥&#xff09;5.3 添加公钥到GIT用户配置中 六 测试git是否可以使用七、总结 一、前言 在使用Git管理…...

爬虫学习-基础(HTTP原理)

目录 一、URL和URI 二、HTTP和HTTPS &#xff08;1&#xff09;HTTP &#xff08;2&#xff09;HTTPS &#xff08;3&#xff09;HTTP与HTTPS区别 &#xff08;4&#xff09;HTTPS对HTTP的改进&#xff1a;双问的身份认证 三、TCP协议 &#xff08;1&#xff09;TCP三次握手…...

Gazebo 中为地面和车轮添加摩擦属性

Gazebo 中为地面和车轮添加摩擦属性 Link friction properties not applied from URDF to Gazebo SDFormat Specification Adding friction to model wheels Gazebo中模型自行滑动&#xff08;后溜&#xff09;的原因探究 移动机器人在仿真时&#xff0c;一旦以较大的速度启动&…...

【重点】【滑动窗口】3. 无重复字符的最长子串

题目 参考《算法小抄》重的解法&#xff0c;重点理解&#xff01;&#xff01;&#xff01; class Solution {public int lengthOfLongestSubstring(String s) {if (s.length() < 2) {return s.length();}char[] array s.toCharArray();int left 0, right 0, res 0;int…...

python初始化矩阵相关

做算法题经常需要初始化一个二维的dp数组 下面两种方法是最常用的 matrix [[0]*n]*n matrix [[0]*n for _ in range(n)]以前经常混用也没发现什么问题&#xff0c;直到昨天debug的时候发现第一种初始化之后对矩阵进行赋值时混乱的&#xff0c;比如matrix[0][1]2会导致所有行…...

C++ :运算符重载

运算符重载&#xff1a; 运算符重载概念&#xff1a;对已有的运算符重新进行定义&#xff0c;赋予其另一种功能&#xff0c;以适应不同的数据类型 运算符的重载实际是一种特殊的函数重载&#xff0c;必须定义一个函数&#xff0c;并告诉C编译器&#xff0c;当遇到该重载的运算符…...

如何跑通跨窗口渲染:multipleWindow3dScene

New 这是一个跨窗口渲染的示例&#xff0c;用 Three.js 和 localStorage 在同一源&#xff08;同产品窗口&#xff09;上跨窗口设置 3D 场景。而这也是本周推特和前端圈的一个热点&#xff0c;有不少人在争相模仿它的实现&#xff0c;如果你对跨窗口的渲染有兴趣&#xff0c;可…...

flutter-web中使用js工具类

文章目录 为什么要调用js1. flutter-web1. 引入js web/index.html2. 创建工具js web/CryptoEnc.js3. 创建对应的lib/js/js_interop.dart4. 由于引入的js是针对web平台的&#xff0c;所以引入需要做引入处理5. 使用 2. Android1. 引入依赖2. index.html3. dart引用 为什么要调用…...

@ResponseBody详解:用于响应体响应数据

RestFul风格或者是web阶段接触过的异步请求&#xff0c;都需要把数据转换成Json放入响应体中。 ResponseBody的作用其实是将java对象转为json格式的相应内容 使用 RequestMapping注解时&#xff0c;Spring会将返回值解析为视图路径&#xff0c;然后跳转路径返回对应的视图页面…...

【Python百练——第3练】矩形类及操作

&#x1f490;作者&#xff1a;insist-- &#x1f490;个人主页&#xff1a;insist-- 的个人主页 理想主义的花&#xff0c;最终会盛开在浪漫主义的土壤里&#xff0c;我们的热情永远不会熄灭&#xff0c;在现实平凡中&#xff0c;我们终将上岸&#xff0c;阳光万里 ❤️欢迎点…...

【C语言学习疑难杂症】C语言中数组存储时为什么从低地址到高地址

在C语言中&#xff0c;数组的存储从低地址到高地址是有其历史原因的。这种设计主要是为了与计算机系统的内存组织方式相一致。 在计算机系统中&#xff0c;内存通常按照字节进行编址&#xff0c;地址从低到高递增。数组在内存中是连续存储的&#xff0c;因此数组的第一个元素&…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...