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

实战项目:贪吃蛇游戏的实现(上)

前言

Hello, 今天我们来一起完成一个实战项目:贪吃蛇

相信大家都不会对这个游戏感到陌生,贪吃蛇游戏是久负盛名的游戏,他和俄罗斯方块,扫雷游戏等游戏位列世界经典游戏之列。这次我们旨在通过实战项目贪吃蛇的实现,从设计到代码的实现来提升我们的编程能力和逻辑运算能力!

游戏效果展示:

贪吃蛇游戏效果演示

1.项目目标:

  • 使用C语言在 Windows环境下的控制台模拟实现经典小游戏贪吃蛇
  • 实现的基本功能:
  • 贪吃蛇地图的绘制
  • 蛇吃食物的功能(上、下、左、右方向的控制键来控制蛇的动作)
  • 蛇撞到墙后立即死亡
  • 蛇撞到自身立即死亡
  • 计算得分
  • 蛇身发的加速和减速
  • 暂停游戏

2.技术要点

C语言函数、枚举、动态内存管理、预处理指令、初步解接触数据结构中的链表。

3.Windows系统工具函数

 3.1Win32API介绍

本次实现贪吃蛇会使用一些Win32API的知识,我们想要顺利的完成任务就要去认真掌握其中的一些函数。

Windows这个多作业系统除了协调应用程序的执行、分配管理、资源管理之外,他还是一个好大吃的服务中心,调用这个服务中心的服务(每一种服务就是一种函数)。可以帮助我们达到开启视窗、描绘图像、使用周边设备等目的,由于这些函数的服务对象是一些应用程序(Application),所以百年称之为Applicatino Programming Interface,简称API函数。WIN32API也是Microsoft Windows32w位平台的应用程序编程接口。

3.2控制台程序

平常我们运行起来的黑框程序其实就是控制台程序。

我们可以使用cmd命令来设置控制台窗口的长和宽:设置控制台窗口的大小,30行,100列

mode con cols=100 lines=30

也可以通过命令设置窗口的名字:

title 贪吃蛇

 

这些能在控制台窗口执行的命令,也可以调用C语言函数system来执行。例如:

#include<stdio.h>
int main()
{//设置控制台窗⼝的⻓宽:设置控制台窗⼝的⼤⼩,30⾏,100列system("mode con cols=100 lines=30");//设置cmd窗⼝名称system("title 贪吃蛇");getchar();return 0;
}

 3.3控制平台上的坐标COORD

COORD是WindowsAPI上定义的一个结构体·,表示一个字符在控制台屏幕上的坐标 

typedef struct _COORD {
SHORT X;
SHORT Y;
} COORD, *PCOORD;

給坐标赋值:

COORD pos = { 10, 15 };

3.4GetStdHandle

GetStdHandle是一个WindowsAPI函数。它用于从一个特定的标准设备(标准输入、标准输出或者是标准错误)中取得一个句柄(用来标识不同设备的数值),使用这个句柄可以操作设备。

HANDLE GetStdHandle(DWORD nStdHandle);

实例:
 

HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);

3.5GetConsoleCursorInfo

 检索有关指定的控制台的屏幕缓冲区堆的光标大小和课件行的信息

BOOL WINAPI GetConsoleCursorInfo(
HANDLE hConsoleOutput,
PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
)

实例:

HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息

3.5.1 CONSOLE_CURSOR_INFO

这个结构体,包含控制台光标信息

typedef struct _CONSOLE_CURSOR_INFO {
DWORD dwSize;
BOOL bVisible;
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
  •  deSize,有光标填充的字符单元格的百分比。此值介于1到100之间。光标外观会随着变化,范围从完全填充单元格到单元底部的水平线条。
  • bVisible,游标的可见性。如果光标可见则此成员为TRUE。
CursorInfo.bVisible = false; //隐藏控制台光标

 3.6SetConsoleCursorInfo

设置指定的控制台屏幕缓冲区光标的大小和可见性。

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);//设置控制台光标状态

3.7 SetConsoleCursorPosition

设置制定控制台屏幕缓冲区中光标位置,我们将想要的设置的光标坐标信息放在COOR来行的pos中,调用SetConsoleCursorPosition的函数将光标的位置设定到指定的位置。

BOOL WINAPI SetConsoleCursorPosition(
HANDLE hConsoleOutput,
COORD 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);
//设置标准输出上光标的位置为pos
SetConsoleCursorPosition(hOutput, pos);
}

3.8GetAsyncKeyState

获取按键情况,这个函数的原型如下:

 

SHORT GetAsyncKeyState(
int vKey
);

将键盘上的每个按键的虚拟键值传递给函数,函数通过返回值来分辨案件的状态。

GetAsyncKeyState的返回值是short类型的,在上一次调用GetAsyncKeyState函数后,如果返回的是16位的short数据,最高位是1,说明按键的状态是按下,如果最高位是0,则按键的状态是抬起;如果最低位被置为1则说明,该按键被按过,否则为0。

如果我们要判断一个案件是否被按过,可以检测GetAsyncKeyState返回值的最低位是否为1.

#define KEY_PRESS(VK) ( (GetAsyncKeyState(VK) & 0x1) ? 1 : 0 )

4.贪吃蛇游戏的设计与分析

4.1地图 

 我们最终想要的贪吃蛇大纲可能就是这个样子,按我们要如何进行的图的布置呢?

 

这里我们不得不在讲一下控制窗台的知识了,如果想要在控制台的窗口指定位置输出信息,我们得知道该位置的坐标,所以首先介绍一下控制窗口的坐标知识。

控制窗口的坐标只是如下所示,横向的是x轴,从左向右依次增长,纵向是Y轴,从上到下一次增长。

 

在游戏地图上,我们打印墙体使用宽字符:□ ;打印蛇身我们使用:●;打印食物‘使用宽字符:★’,普通的字符只占一个字节,这类宽字符是占用2个字节。

这里简单的讲一下C语言国际化特性相关的知识,过去C语言并不适合非英语的国家(地区)使用。

C语言最初假定假定字符都是自己的。但是这些假定并不是在世界所有的地方都适用。

后来C鱼啊一年适应到了国际化,C语言标准中不断加入国际化的支持,比如:加入和宽字符的类型wchar_t和宽字符的输入和输出函数,加入<locale.h>头文件,其中提供了允许程序员针对特定地区(通常是国家或者说特定语言的地理地区)调整程序行为的函数。

4.1.1<locale.h>本地化

<locale.h>提供的函数用于控制C语言标准库中对于不同地区会产生的不一样行为的部分·。
在标准可以中,依赖地区的部分有以下几项:

  • 数字量的格式
  • 货币量的格式
  • 字符集
  • 日期和时间的表示形式

 4.1.2类项

通过修改地区,程序可以改变它的行为来适应世界的不同区域。单区域的改变可能影响库的许多部分其中一部分可能使我们不希望改变的。所以C语言针对不同的类项进行修改,下面的一个宏,指定一个类项:

• LC_COLLATE

• LC_CTYPE

• LC_MONETARY

setlocale(LC_ALL, "C");

• LC_NUMERIC

• LC_TIME

• LC_ALL - 针对所有类项修改

4.1.3 setlocale函数

char* setlocale (int category, const char* locale);

setlocale函数用于修改当前的地区,可以针对一个类想项修改,也可以针对所有的类项修改。

setlocale的·第一个参数可以是前面说明的类项中的一个,那么每次只会影响一个类项,如果第一个·参数是LC_ALL,就会影响所有的类项。

C标准给定的第二个参数仅定义了两种可能得取值:“c” 和“ ”。

在任意程序运行是,都会隐藏式执行调用:

setlocale(LC_ALL, "C");

当地区设置为"c"时,库函数按正常的方式执行,小数点是一个点。

的那个吃呢工序运行起来之后想要改变地区,就只能显示调用setlocale函数。用“”作为第二个参数,调用setlocale函数就可以切回到本地模式,这中模式下程序 会适应本地环境。比如:切换到我们本地模式后就支持宽字符(汉字的输出)等。

setlocale(LC_ALL, " ");//切换到本地环境

4.1.4宽字符的打印

那如果想在屏幕上打印宽字符,怎么打印呢?

 

#include <stdio.h>
#include<locale.h>
int main() {
setlocale(LC_ALL, ""
wchar_t ch1 = L'●';
wchar_t ch2 = L'⽐';
wchar_t ch3 = L'特';
wchar_t ch4 = L'★';
printf("%c%c\n", 'a', 'b');
wprintf(L"%c\n", ch1);
wprintf(L"%c\n", ch2);
wprintf(L"%c\n", ch3);
wprintf(L"%c\n", ch4);
return 0;
}

从输出来看,我们发现一个普通的字符占一个字符的位置但是打印一个汉字字符,占用2个字符的位置,那么我们如果在贪吃蛇中使用宽字符,就得憨憨处理地图上的坐标计算。

1个坐标1个正常字符

2个坐标可以存放一个宽字符 

 4.1.5地图坐标

我们假设实现一个棋盘27行,58列的棋盘(行和列可以根据自己的爱好设计修改),再围绕地图画出墙如下:
 

4.2蛇身和食物

初始化状态,假设蛇的长度为5,蛇身上的·节点是●,在固定的一个坐标处,比如(24,5)处开始出现蛇,连续5个节点。注意:蛇的每个节点的x坐标必须是2的倍数,否则可能出现蛇的一个节点有一半出现在墙体中。另外一半在墙体外的现象,坐标不好对齐。

关于食物,就是在墙体内随机生成一个坐标(X坐标必须是2的倍数),坐标不能和蛇的身体重合,让后打印★ 

 

相关文章:

实战项目:贪吃蛇游戏的实现(上)

前言 Hello, 今天我们来一起完成一个实战项目&#xff1a;贪吃蛇。 相信大家都不会对这个游戏感到陌生&#xff0c;贪吃蛇游戏是久负盛名的游戏&#xff0c;他和俄罗斯方块&#xff0c;扫雷游戏等游戏位列世界经典游戏之列。这次我们旨在通过实战项目贪吃蛇的实现&#xff0c…...

SHT30温湿度传感器全解析——概况,性能,MCU连接,样例代码

常见温湿度传感器测量范围&#xff1a;(价格仅供参考&#xff0c;具体性能要看折线图) 型号DHT11DHT20AHT10AHT20AHT30SHT20价格&#xffe5; 2.49&#xffe5;3.04&#xffe5; 1.9&#xffe5;1.4&#xffe5; 1.3&#xffe5;5.5温度测量范围20—90%RH0—100%RH0—100%RH0—…...

SQL server 同环比计算模板

1、计算 月 年 季度的环比和同比 计算公式如下&#xff1a; 环比增长率 &#xff08;本期数 - 上期数&#xff09; / |上期数| 100% 同比增长率 &#xff08;本期数 - 同期数&#xff09; / |同期数| * 100% --- dbo.ads_erp_finance_gross_profit_actual_invoice_yoy_m…...

python发送外部请求

在Python中&#xff0c;服务器发送外部请求是一个常见的操作&#xff0c;尤其是在需要集成不同服务或API时。有多种库可以帮助你完成这项任务&#xff0c;但最流行和广泛使用的库之一是requests。以下是如何使用requests库在Python服务器中发送外部请求的基本步骤&#xff1a; …...

c++并发编程面试题

1. C中lock_guard和unique_lock的区别&#xff1f; 在C中&#xff0c;lock_guard和unique_lock都是用于管理互斥锁的类&#xff0c;它们提供了一种 RAII&#xff08;Resource Acquisition Is Initialization&#xff09;机制来确保锁在作用域结束时自动释放。尽管它们的目的相…...

K8S上安装LongHorn(分布式块存储) --use

要在 Kubernetes上安装 LongHorn&#xff0c;您可以按照以下步骤进行操作&#xff1a; 准备工作 参考 官网教程将LongHorn只部署在k8s-worker5节点上。https://github.com/longhorn/longhorn 安装要求 Each node in the Kubernetes cluster where Longhorn is installed must f…...

2024年前端技术发展趋势分析

2024年的前端技术发展趋势继续受到快速变化的技术环境和不断增长的用户期望的影响。以下是2024年前端技术发展的几个关键趋势&#xff1a; 1. Web 组件和自定义元素 Web 组件技术&#xff08;包括 Shadow DOM、HTML Templates 和 Custom Elements&#xff09;正在成为构建可重…...

spring boot 笔记大杂烩

一&#xff0c;springboot项目创建 springboot创建时idea会打开start.spring.io失败报错 可以手动打开这个页面&#xff0c;然后选择maven项目&#xff0c;然后修改group和name名然后添加依赖web&#xff0c;然后生成项目包&#xff0c;解压缩后用idea打开就能用了 运行后报错…...

如何在香港云服务器上优化网站性能?

在香港云服务器上优化网站性能可以通过以下几种方式进行&#xff0c;确保用户从全球各地访问时获得快速、稳定的体验&#xff1a; 1. 使用内容分发网络 (CDN) 优势&#xff1a;CDN可以将静态内容&#xff08;如图像、视频、CSS、JavaScript文件&#xff09;缓存到全球多个节点…...

STM32低功耗与备用备份区域

STM的备份备用区域其实就是两个区块&#xff1a;BKP和RTC。低功耗则其实是STM32四种模式中的三种耗能很低的模式。 目录 一&#xff1a;备用区域 1.BKP 2.RTC 二&#xff1a;低功耗模式 1.睡眠模式&#xff1a; 2.停机模式&#xff1a; 3.待机模式&#xff1a; 一&…...

武汉某汽配公司携手三品软件 共绘PLM项目新蓝图

近日&#xff0c;三品软件与武汉某汽配公司达成战略合作&#xff0c;双方将共同启动PLM项目&#xff0c;以助力该公司在汽车制造业的研发管理领域实现全面升级。 客户简介 该公司自2008年成立以来&#xff0c;一直专注于为汽车制造业提供自动化输送系统、车辆装配的合装技术和…...

uniapp多图上传uni.chooseImage上传照片uni.uploadFile,默认上传9张图

uniapp多图上传uni.chooseImage上传照片uni.uploadFile 代码示例&#xff1a; /**上传照片 多图*/getImage() {uni.chooseImage({count: 9, //默认9sizeType: [original, compressed], //可以指定是原图还是压缩图&#xff0c;默认二者都有sourceType: [album], //从相册选择/…...

MySQL——内置函数

时间函数 select * from msg where date_add(sendtime, interval 2 minute) > now(); 理解&#xff1a; ------------------------------|-----------|-------------|------------------ 初始时间 now() 初始时间2min 字符串 length函数返回字符串长度&#xff0c;以字节为…...

2024年最新版小程序云开发数据模型的开通步骤,支持可视化数据库管理,支持Mysql和NoSql数据库,可以在vue3前端web里调用操作

小程序官方又改版了&#xff0c;搞得石头哥不得不紧急的再新出一版&#xff0c;教大家开通最新版的数据模型。官方既然主推数据模型&#xff0c;那我们就先看看看新版的数据模型到底是什么。 一&#xff0c;什么是数据模型 数据模型是什么 数据模型是一个用于组织和管理数据的…...

智慧水库大坝安全监测预警系统解决方案

前言 水库大坝作为重要的水利设施&#xff0c;承载着防洪涝、灌溉、发电等功能&#xff0c;关系着无数人的生命财产安全&#xff0c;一旦发生意外事故&#xff0c;后果将不堪设想&#xff0c;因此需要建立一套水库大坝安全监测预警系统解决方案。 系统概述 水库大坝安全监测…...

基于SpringBoot+VUE的社区团购系统(源码+文档+部署)

主要内容&#xff1a;Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能与大数据、单片机开发、物联网设计与开发设计、简历模板、学习资料、面试题库、技术互助、就业指导等 业务范围&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写…...

LeetCode 3151. 特殊数组 I【数组】简单【Py3,C++,Java,GO,Rust】

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

超级字符串技能:提升你的编码游戏

嘿嘿,uu们,今天咱们来详解字符函数与字符串函数,好啦,废话不多讲,开干&#xff01; 1.:字符分类函数 C语言中又一系列的函数是专门做字符分类的,也就是一个字符属于什么类型的字符的,这些函数的使用需要包含头文件ctype.h 这些函数的使用方法都十分类似,博主在这里就举两到三个…...

米联客-FPGA程序设计Verilog语法入门篇连载-16 Verilog语法_时钟分频设计

软件版本&#xff1a;无 操作系统&#xff1a;WIN10 64bit 硬件平台&#xff1a;适用所有系列FPGA 板卡获取平台&#xff1a;https://milianke.tmall.com/ 登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑&#xff01; 1概述 本小节讲解Verilog语法的时钟…...

【Echarts】custom自定义图表实现甘特图

效果图 主要注意点&#xff1a; 1、右上角图例visualMap实现 2、visualMap增加formatter 3、series使用custom自定义图表&#xff0c;encode解析四维数组。核心是renderItem方法&#xff0c;必填项&#xff0c;且需要注意要全部定义在options里面&#xff01;&#xff01;&…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 &#xff08;一&#xff09;引用计数法 &#xff08;二&#xff09;可达性分析算法 二、垃圾回收算法 &#xff08;一&#xff09;标记清除 &#xff08;二&#xff09;标记整理 &#xff08;三&#xff09;复制 &#xff08;四&#xff…...

macOS 终端智能代理检测

&#x1f9e0; 终端智能代理检测&#xff1a;自动判断是否需要设置代理访问 GitHub 在开发中&#xff0c;使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新&#xff0c;例如&#xff1a; fatal: unable to access https://github.com/ohmyzsh/oh…...