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)
目录 🎇测试游戏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 };//创建…...
Comparator接口
Comparator接口 Comparator 是 Java 中用于比较对象的接口。它允许开发者实现自定义的比较逻辑,以用于对对象进行排序或者确定它们的顺序。 主要方法: Comparator 接口中包含一个抽象方法: int compare(T o1, T o2):用于比较两…...
SELinux refpolicy详解(9)
接前一篇文章:SELinux refpolicy详解(8) 三、refpolicy内容详解 上一回讲解了refpolicy源码根目录下的build.conf文件的前一部分内容。本回继续讲解其后一部分。 2. build.conf 文件路径:refpolicy源码根目录/build.conf。 文…...

零基础上手,秒识别检测,IDEA研究院发布全新T-Rex模型
目标检测作为当前计算机视觉落地的热点技术之一,已被广泛应用于自动驾驶、智慧园区、工业检测和卫星遥感等场景。开发者在研究相关目标检测技术时,通常需熟练掌握图像目标检测框架,如通用目标检测框架 YOLO 系列,旋转目标检测框架…...
python每日一题——20旋转图像
题目 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1: 输入:matrix [[1,2,3],[4,5,6],[7,8,9]]…...

云计算生成式 -给你不一样的音乐推荐新体验
目录 摘要: 正文: 一、亚马逊云与生成式 AI 结合的展望/总结 二、我用亚马逊云科技生成式 AI 产品打造了什么,解决了什么问题 三、未来云端技术发展趋势的见解 四、云端技术未来需要解决的问题 1、如何保护数据安全和隐私? …...

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

基于PHP的高中生物学习平台
有需要请加文章底部Q哦 可远程调试 基于PHP的高中生物学习平台 一 介绍 此高中生物学习平台基于原生PHP开发,数据库mysql。系统角色分为用户和管理员。(附带参考设计文档) 技术栈:phpmysqlphpstudyvscode 二 功能 学生 1 注册/登录/注销 2 个人中心 …...
Git多库多账号本地SSH连接配置方法
Git多库多账号本地SSH连接配置方法 一、前言二、环境三、帮助文档四、多环境配置4.1 配置config文件 五、生成RSA秘钥对5.1 ssh秘钥位置5.2 生成秘钥对(公钥、私钥)5.3 添加公钥到GIT用户配置中 六 测试git是否可以使用七、总结 一、前言 在使用Git管理…...

爬虫学习-基础(HTTP原理)
目录 一、URL和URI 二、HTTP和HTTPS (1)HTTP (2)HTTPS (3)HTTP与HTTPS区别 (4)HTTPS对HTTP的改进:双问的身份认证 三、TCP协议 (1)TCP三次握手…...
Gazebo 中为地面和车轮添加摩擦属性
Gazebo 中为地面和车轮添加摩擦属性 Link friction properties not applied from URDF to Gazebo SDFormat Specification Adding friction to model wheels Gazebo中模型自行滑动(后溜)的原因探究 移动机器人在仿真时,一旦以较大的速度启动&…...
【重点】【滑动窗口】3. 无重复字符的最长子串
题目 参考《算法小抄》重的解法,重点理解!!! 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)]以前经常混用也没发现什么问题,直到昨天debug的时候发现第一种初始化之后对矩阵进行赋值时混乱的,比如matrix[0][1]2会导致所有行…...

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

如何跑通跨窗口渲染:multipleWindow3dScene
New 这是一个跨窗口渲染的示例,用 Three.js 和 localStorage 在同一源(同产品窗口)上跨窗口设置 3D 场景。而这也是本周推特和前端圈的一个热点,有不少人在争相模仿它的实现,如果你对跨窗口的渲染有兴趣,可…...
flutter-web中使用js工具类
文章目录 为什么要调用js1. flutter-web1. 引入js web/index.html2. 创建工具js web/CryptoEnc.js3. 创建对应的lib/js/js_interop.dart4. 由于引入的js是针对web平台的,所以引入需要做引入处理5. 使用 2. Android1. 引入依赖2. index.html3. dart引用 为什么要调用…...
@ResponseBody详解:用于响应体响应数据
RestFul风格或者是web阶段接触过的异步请求,都需要把数据转换成Json放入响应体中。 ResponseBody的作用其实是将java对象转为json格式的相应内容 使用 RequestMapping注解时,Spring会将返回值解析为视图路径,然后跳转路径返回对应的视图页面…...

【Python百练——第3练】矩形类及操作
💐作者:insist-- 💐个人主页:insist-- 的个人主页 理想主义的花,最终会盛开在浪漫主义的土壤里,我们的热情永远不会熄灭,在现实平凡中,我们终将上岸,阳光万里 ❤️欢迎点…...
【C语言学习疑难杂症】C语言中数组存储时为什么从低地址到高地址
在C语言中,数组的存储从低地址到高地址是有其历史原因的。这种设计主要是为了与计算机系统的内存组织方式相一致。 在计算机系统中,内存通常按照字节进行编址,地址从低到高递增。数组在内存中是连续存储的,因此数组的第一个元素&…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ 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解题:3564. 季节性销售分析 题目: 表: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征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

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

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...