【C语言项目】贪吃蛇(上)

个人主页 ~
gitee仓库~
欢迎大家来到C语言系列的最后一个篇章–贪吃蛇游戏的实现,当我们实现了贪吃蛇之后,我们的C语言就算是登堂入室了,基本会使用了,当然,想要更加熟练地使用还需要多多练习
贪吃蛇
- 一、目标
- 二、需要的知识
- 1、Win32 API概念
- 2、控制台程序
- (1)mode命令
- (2)COORD坐标
- (3)隐藏光标的操作
- ①GetStdHandle
- ②GetConsoleCursorlnfo
- ③CONSOLE_CURSOR_INFO
- ④SetConsoleCursorInfo
- ⑤SetConsoleCursorPosition
- 封装一个函数命名为SetPos,专门用来设置光标位置
- (4)GetAsyncKeyState
- 三、游戏设计与分析
- 1、地图
- (1)本地化
- (2)类项
- (3)setlocale
- (4)宽字符的打印
- (5)地图坐标
- 2、蛇身和食物
- 3、数据结构设计
- 4、设计游戏流程
一、目标
使用C语言在Windows环境的控制台中模拟实现贪吃蛇游戏
功能:
①贪吃蛇地图
②蛇的移动
③蛇吃食物
④蛇撞墙或者撞到自己死亡
⑤计算得分
⑥暂停游戏
⑦加速蛇身
⑧计算得分
二、需要的知识
函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32 API
其中只有Win32 API我们在之前的博文中没有提到过,这里我们一起着重学习一下
1、Win32 API概念
Application Programming Interface(应用程序编程接口),简称API函数。
Windows是一个多作业系统,它除了协调应用程序的执行、分配内存、管理资源之外,也是一个很大的服务中心,调用这个服务中心的各种服务,其中每一种服务就是一个函数,可以帮应用程序达到开启视窗、描绘图形、使用周边设备等目的,这些函数服务的对象就是应用程序Application
Win32 API就是Windows32位平台的应用程序编程接口
2、控制台程序
在控制台能够执行的命令在编译器中也可以使用system函数来执行
(1)mode命令
mode con cols=100 lines=30;
#include <stdio.h>
int main()
{//设置控制台的大小为三十行一百列system("mode con cols=100 lines=30");//设置cmd窗⼝名称system("title 贪吃蛇"); return 0;
}
(2)COORD坐标
COORD是Windows API中的一个结构体,表示一个字符在控制台屏幕上的坐标,左上角的坐标为(0,0)

COORD中有两个short值,一个为x,一个为y
typedef struct _COORD
{SHORT X;SHORT Y;
}COORD,*PCOORD;
COORD p = {10,20};//给坐标赋值
(3)隐藏光标的操作
在游戏的过程中,我们需要打印蛇身,墙壁,食物等,当我们在进行游戏时,是看不到光标闪烁的,但光标是存在的,所以我们要将它们隐藏
①GetStdHandle
GetStdHandle也是一个Windows API函数,它用于从一个特定的设备(标准输入、标准输出、标准错误)中获得一个句柄,使用这个句柄可以操作设备
HANDLE GetStdHandle(DWORD nStdHandle);
②GetConsoleCursorlnfo
检索有关指定控制台屏幕缓冲区的光标大小和可见性的信息
BOOL WINAPI GetConsoleCursorInfo
(HANDLE hConsoleoutput,PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
);
//PCONSOLE_CURSOR_INFO是指向CONSOLE_CURSOR_INFO结构的指针
使用:
HANDLE houtput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
houtput = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(houtput, &CursorInfo);//获取控制台光标信息
③CONSOLE_CURSOR_INFO
包含有关控制台光标的信息,是个结构体
typedef struct _CONSOLE_CURSOR_INFO
{DWORD dwSize;//光标填充单元格的百分比,此值介于1-100,光标外观会发生变化BOOL bVisible;//游标的可见性,如果游标可见,其为TRUE,不可见为FALSE
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
④SetConsoleCursorInfo
设置指定控制台屏幕缓冲区的光标大小和可见性
BOOL WINAPI SetConsoleCursorInfo
(HANDLE hConsoleoutput,const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo
);
使用:
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
//影藏光标操作
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(houtput, &CursorInfo);//获取控制台光标信息
CursorInfo.bVisible = false; //隐藏控制台光标
SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态
⑤SetConsoleCursorPosition
设置指定控制台屏幕缓冲区中的光标位置
BOOL WINAPI SetConsoleCursorPosition
(HANDLE hConsoleoutput,COORD pos
);
我们将想要设置的坐标信息放在pos当中,调用该函数将光标位置设置到指定的位置
使用:
COORD pos = {10, 5};
HANDLE houtput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
houtput = GetStdHandle(STD_OUTPUT_HANDLE);
//设置标准输出上光标的位置为pos
SetConsoleCursorPosition(hOutput, pos);
封装一个函数命名为SetPos,专门用来设置光标位置
void SetPos(short x, short y)
{COORD pos = { x, y };HANDLE houtput = NULL;//获取标准输出的句柄(⽤来标识不同设备的数值)houtput = GetStdHandle(STD_OUTPUT_HANDLE);//设置标准输出上光标的位置为posSetConsoleCursorPosition(houtput, pos);
}
(4)GetAsyncKeyState
原型:
SHORT GetAsyncKeyState
(int vKey
);
这个函数可以通过检测游戏进行时的按键来传递相应的返回值,可以实时监测此时按键的状态,调用后,如果该键按下返回的short值的最高位为1,否则为0,所以我们定义一个宏,来判断该键是否被按下
#define KEY_PRESS(VK) ( (GetAsyncKeyState(VK) & 0x1) ? 1 : 0 )
括号里是虚拟键代码,填入相应的虚拟键代码可以检测键是否被按下
三、游戏设计与分析
1、地图

在游戏中墙体、蛇体以及食物的打印用的是宽字符,占用两个字符,因为一个字符的话游戏会相当不美观,因为x轴的1和y轴的1的长度不同,y轴的1的长度约等于x轴的1的两倍
x=y=1时:

x=2,y=1时:

我们可以明显看出格子的区别
在宽字符打印之前我们要进行本地化
(1)本地化
包含头文件<local.h>
(2)类项
①LC_COLLATE:影响字符串比较函数strcoll和strxfrm
②LC_CTYPE:影响字符处理函数的行为
③LC_MONETARY:影响货币格式
④LC_NUMERIC:影响printf的数字格式
⑤LC_TIME:影响时间格式strftime和wcsftime
⑥LC_ALL:以上所有类别全部修改
(3)setlocale
char* setlocale (int category, const char* locale);
该函数用来修改当前地区
第一个
第二个参数仅定义了两种可能的取值:
“C”正常模式
“ ”本地模式
切换到本地模式就可以支持宽字符的打印
setlocale(LC_ALL, "C");//正常模式
setlocale(LC_ALL, " ");//本地模式
(4)宽字符的打印
可以把宽字符看做是长的字符
#include <stdio.h>
#include <locale.h>
int main()
{
setlocale(LC_ALL, "");
wchar_t c = L's';
wchar_t s = L"little_monster";
wprintf(L"%lc",c);
wprintf(L"%ls",s);
}
(5)地图坐标
这里我们实现的地图是27*58的,围绕边缘打印一周墙体
2、蛇身和食物
开始时,假设蛇长度为5,蛇身的每个节点用◆符号,在一个固定的连续5个坐标放蛇身
蛇的每个节点的x坐标都是2的倍数(宽字符),否则会出现一半节点在里边一半节点在墙里
食物节点的x坐标也是2的倍数,并且坐标不能与蛇身重合
3、数据结构设计
游戏运行过程中,蛇每吃掉一个食物蛇体就增加一个节点,每个节点就存储当前的坐标以及下一个节点的坐标
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 _Socre;//游戏当前获得分数int _foodWeight;//默认每个⻝物10分int _SleepTime;//每⾛⼀步休眠时间
}Snake, * pSnake;
蛇的方向我们用枚举,因为蛇的行进方向只能有一个,使用枚举可以减小内存的占用
enum DIRECTION
{UP = 1,DOWN,LEFT,RIGHT
};
游戏状态我们也用枚举,理由同上,状态只能有一个
enum GAME_STATUS
{OK,//正常运⾏KILL_BY_WALL,//撞墙KILL_BY_SELF,//咬到⾃⼰END_NOMAL//正常结束
};
4、设计游戏流程

当我们把整个框架定好,下一步就可以来实现游戏了
下一篇再见~

相关文章:
【C语言项目】贪吃蛇(上)
个人主页 ~ gitee仓库~ 欢迎大家来到C语言系列的最后一个篇章–贪吃蛇游戏的实现,当我们实现了贪吃蛇之后,我们的C语言就算是登堂入室了,基本会使用了,当然,想要更加熟练地使用还需要多多练习 贪吃蛇 一、目标二、需要…...
LeNet-5上手敲代码
LeNet-5 LeNet-5由Yann LeCun在1998年提出,旨在解决手写数字识别问题,被认为是卷积神经网络的开创性工作之一。该网络是第一个被广泛应用于数字图像识别的神经网络之一,也是深度学习领域的里程碑之一。 LeNet-5的整体架构: 总体…...
javaWeb入门(自用)
1. vue学习 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script src"https://unpkg.com/vue2"></script> </head> <body><div id"…...
web3风格的网页怎么设计?分享几个,找找感觉。
web3风格的网站是指基于区块链技术和去中心化理念的网站设计风格。这种设计风格强调开放性、透明性和用户自治,体现了Web3的核心价值观。 以下是一些常见的Web3风格网站设计元素: 去中心化标志:在网站的设计中使用去中心化的标志࿰…...
ASP.NET MVC(-)表单的提交、获取表单数据
FromCollection 方式...
[AIGC] 《MyBatis-Plus 结合 Spring Boot 的动态数据源介绍及 Demo 演示》
在现代的 Web 应用开发中,Spring Boot 已经成为了一种流行的框架选择。而 MyBatis-Plus 则为 MyBatis 框架提供了更强大的功能和便利。当它们结合使用时,动态数据源的运用变得更加简单和高效。 动态数据源的概念允许我们在运行时根据不同的条件或需求选…...
【华为OD机试C卷D卷】部门人力分配(C++/Java/Python)
【华为OD机试】-(A卷+B卷+C卷+D卷)-2024真题合集目录 【华为OD机试】-(C卷+D卷)-2024最新真题目录 题目描述 部门在进行需求开发时需要进行人力安排。 当前部门需要完成 N 个需求,需求用 requirements 表述,requirements[i] 表示第 i 个需求的工作量大小,单位:人月。 这部…...
毕业设计:《基于 Prometheus 和 ELK 的基础平台监控系统设计与实现》
前言 《基于 Prometheus 和 ELK 的基础平台监控系统设计与实现》,这是我在本科阶段的毕业设计,通过引入 Prometheus 和 ELK 架构实现企业对指标与日志的全方位监控。并且基于云原生,使用容器化持续集成部署的开发方式,通过 Sprin…...
docker私有仓库部署与管理
一、搭建本地公有仓库 1.1 首先下载registry镜像 docker pull registry 1.2 在daemon.json文件中添加私有镜像仓库地址并重新启动docker服务 vim /etc/docker/daemon.json 1.3 运行registry容器 docker run -itd -v /data/registry:/var/lib/registry -p 5000:5000 --restartal…...
2024第六届济南国际大健康产业博会将于5月27日如期开幕
由山东省城市经济学会、山东省科学养生协会主办的第六届中国(济南)国际大健康产业博览会,将于5月27-29日,在济南黄河国际会展中心盛大举办。 近年来,健康越来越受到大众的重视,在我国经济重要的转型阶段成…...
计算方法实验9:Romberg积分求解速度、位移
任务 输出质点的轨迹 ( x ( t ) , y ( t ) ) , t ∈ { 0.1 , 0.2 , 0.3 , . . . , 10 } (x(t), y(t)), t\in \{0.1, 0.2, 0.3, ..., 10\} (x(t),y(t)),t∈{0.1,0.2,0.3,...,10},并在二维平面中画出该轨迹.请比较M分别取4, 8, 12, 16, 20 时,Romberg积分达…...
设计模式有哪些基本原则
目录 开闭原则(Open Closed Principle) 里氏替换原则(Liskov Substitution principle) 单一职责原则(Single Responsibility Principle,SRP)...
别再出错了!华为交换机到底如何配置access、trunk、hybird端口?
号主:老杨丨11年资深网络工程师,更多网工提升干货,请关注公众号:网络工程师俱乐部 下午好,我的网工朋友。 我们都知道,网络工程师的工作离不开对交换机的熟练操作。华为交换机的配置,绝对是考验…...
OceanBase 分布式数据库【信创/国产化】- OceanBase 平台产品 - 迁移评估工具 OMA
本心、输入输出、结果 文章目录 OceanBase 分布式数据库【信创/国产化】- OceanBase 平台产品 - 迁移评估工具 OMA前言OceanBase 数据更新架构OceanBase 平台产品 - 迁移评估工具 OMA兼容性评估性能评估导出 OceanBase 数据库对象和 SQL 语句OceanBase 分布式数据库【信创/国产…...
UE5入门学习笔记(六)——编译低版本插件
对于有些低版本的插件,可以通过此方法自己编译到高版本而无需等待插件作者更新 使用工具:如图所示 步骤1:打开cmd,并使用cd命令切换到此目录 步骤2:输入如下指令 RunUAT.bat BuildPlugin -Plugin“路径1” -Package“…...
MySQL全局锁、表级锁、行锁、死锁、索引选择
文章目录 全局锁表级锁表锁元数据锁 MDL 如何安全的给小表添加字段1. 理解和监控长事务2. 使用NOWAIT和WAIT语法示例 3. 选择合适的时间窗口4. 分阶段执行5. 使用在线DDL工具 行锁死锁普通索引和唯一索引的选择索引基础业务场景分析性能考量实践建议索引及其选择机制索引选择错…...
深入解析算法效率核心:时间与空间复杂度概览及优化策略
算法复杂度,即时间复杂度与空间复杂度,衡量算法运行时资源消耗。时间复杂度反映执行时间随数据规模增长的关系,空间复杂度表明额外内存需求。优化策略,如选择合适数据结构、算法改进、循环展开等,对于提升程序效率、减…...
虚拟机装CentOS镜像
起先,是先安装一个VM虚拟机,再去官方网站之类的下载一些镜像,常见镜像有CentOS镜像,ubantu镜像,好像还有一个树莓还是什么的,软件这块,日新月异,更新太快,好久没碰&#…...
SpringCloud 集成consul,消费者报I/O error on GET request for...
创建消费者微服务,去调用生产者微服务的请求过程中,出现以下错误: 报错原因 因为在使用SpringCloudAlibaba中的Nacos框架时,自动整合了SpringCloud中的Ribbon框架中的负载均衡,因为微服务提供者有两个,在消…...
pytest的测试标记marks
引用打标的marks文档 Python的pytest框架(5)--测试标记(Markers)_pytest执行指定的marker-CSDN博客 https://www.cnblogs.com/pipile/p/12696226.html 给用例自定义打标签的代码示例 #coding:utf-8 import pytest pytest.mark.smoke def test_1():print("smoke的测试用…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
