C语言小游戏:贪吃蛇(游戏开发的环境和功能介绍)
❀❀❀ 文章由@不准备秃的大伟原创 ❀❀❀
♪♪♪ 若有转载,请联系博主哦~ ♪♪♪
❤❤❤ 致力学好编程的宝藏博主,代码兴国!❤❤❤
生命不停,学习不止。铁汁们,我是大伟,欢迎来到大伟的游戏时间,今天带大家来玩一款几乎是所有人童年的记忆中的一款经典的不能再经典的游戏:贪吃蛇!
当然了,在玩游戏前,我们还是要先把游戏写出来啦!○( ^皿^)っHiahiahia…

废话不多说,在开始游戏前,有些知识是希望大家了解的(因为博主也不是很懂,所以只能理解了,QWQ) 。
由于我们的贪吃蛇游戏是在我们windows电脑的控制台上实现的,所以我想带大家了解一下Win32 API:
我们的小度娘给Win32 API的介绍是:
Windows这个多作业系统除了协调应⽤程序的执⾏、分配内存、管理资源之外,它同时也是⼀个很⼤ 的服务中⼼,调⽤这个服务中⼼的各种服务(每⼀种服务就是⼀个函数),可以帮应⽤程序达到开启 视窗、描绘图形、使⽤周边设备等⽬的,由于这些函数服务的对象是应⽤程序(Application),所以便 称之为Application Programming Interface,简称 API 函数。WIN32 API也就是Microsoft Windows 32位平台的应⽤程序编程接⼝。
听起来很高级是吧~嗯,雀食蛮高级的,但是作为我们使用的人来说并不需要了解这么多,会用就好了,对吧?
首先,不知道有没有铁汁的VS操作台是和大伟一样是这样的?->
上面这个窗口其实是VS的操作台,而我们需要的是我们电脑的Windows操作台,该怎么切换呢?其实很简单: 
这样子就切换成功了,大家来看一看效果:
是不是瞬间就有玩游戏的感觉了?哈哈 (^▽^ )
那这个时候就有铁汁好奇了,说:“大伟啊,你这个运行框的名字是‘贪吃蛇’,而且屏幕上有一串文字,窗口大小也和我的不一样,怎么回事啊?” ,诶,别急嘛,接下来就会教你滴~
一. 设置控制台:
我们可以使⽤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 贪吃蛇"); return 0;
}
此外,我们还可以调控制台屏幕上的坐标COORD,而COORD是Windows API中定义的⼀个结构体,表⽰⼀个字符在控制台屏幕上的坐标,如下:
typedef struct _COORD {SHORT X;SHORT Y;
} COORD, *PCOORD;//给坐标赋值
COORD pos = { 10, 15 };
这个时候,我们的光标就会在坐标为(10,15)的地方闪烁,但是,我们会发现在游戏进行的时候,我们看不到光标的闪烁,这又该怎么做呢?
这个时候就要用到GetStdHandle了,那这是啥呢?
GetStdHandle是⼀个Windows API函数。它⽤于从⼀个特定的标准设备(标准输⼊、标准输出或标 准错误)中取得⼀个句柄(⽤来标识不同设备的数值),使⽤这个句柄可以操作设备。
原代码声明如下:GetStdHandle 函数 - Windows Console | Microsoft Learn
HANDLE GetStdHandle(DWORD nStdHandle);
我们可以写出如下代码:
HANDLE handle = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
handle = GetStdHandle(STD_OUTPUT_HANDLE);
这时候获得了句柄,我们可以用函数 GetConsoleCursorInfo 获得光标的信息,源代码声明如下:GetConsoleCursorInfo 函数 - Windows Console | Microsoft Learn
BOOL WINAPI GetConsoleCursorInfo(
HANDLE hConsoleOutput,PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
);
我们可以这样运用:
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;BOOL bVisible;
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;
其中:
1. dwSize:由光标填充的字符单元格的百分⽐。此值介于1到100之间。光标外观会变化,范围从完全填充单元格到单元底部的⽔平线条。
2. bVisible:游标的可⻅性。如果光标可⻅,则此成员为TRUE。
之后我们可以用SetConsoleCursorInfo设置指定控制台屏幕缓冲区的光标的⼤⼩和可⻅性。SetConsoleCursorInfo的源代码声明如下:SetConsoleCursorInfo 函数 - Windows Console | Microsoft Learn
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);//设置控制台光标状态
而为了设置指定控制台屏幕缓冲区中的光标位置,我们将想要设置的坐标信息放在COORD类型的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);
}
此外,我们需要操作↑ ↓ ← → 键来操作蛇的移动,所以我们需要一个函数来检测键盘按键是否被按下,而函数GetAsyncKeyState就可以做到,源代码声明如下:GetAsyncKeyState function (winuser.h) - Win32 apps | Microsoft Learn
SHORT GetAsyncKeyState(int vKey
);
我们需要将键盘上每个键的虚拟键值传递给函数,函数通过返回值来分辨按键的状态。
GetAsyncKeyState 的返回值是short类型,在上⼀次调⽤ GetAsyncKeyState 函数后,如果 返回的16位的short数据中,最⾼位是1,说明按键的状态是按下,如果最⾼是0,说明按键的状态是抬起;如果最低位被置为1则说明,该按键被按过,否则为0。
如果我们要判断⼀个键是否被按过,可以检测GetAsyncKeyState返回值的最低值是否为1,因此我们可以定义一个宏:
#define KEY_PRESS(VK) ( (GetAsyncKeyState(VK) & 1) ? 1 : 0 )
这样就可以检测我们的键盘是否被按下了。
二.贪吃蛇游戏的设计分析
首先,我们玩贪吃蛇,都会有个地图吧(限制蛇的运动范围),那我们该如何布置我们的地图呢?这个时候就不得不谈到控制台窗口的一些知识,如果想在控制台的窗⼝中指定位置输出信息,我们得知道该位置的坐标,所以⾸先介绍⼀下控制台窗⼝的坐标知识
控制台窗⼝的坐标如下所⽰,横向的是X轴,从左向右依次增⻓,纵向是Y轴,从上到下依次增⻓
在游戏地图上,我们打印墙体使⽤宽字符:□,打印蛇使⽤宽字符●,打印⻝物使⽤宽字符★ 普通的字符是占⼀个字节的,这类宽字符是占⽤2个字节。而为了打印这些字节,我们需要在这些宽字符前加上大写的'L',我们还需要将 printf 改为 wprintf ,wprintf是专门来打印宽字符的,如下:
wprintf(L"%c", □);
通过输出的结果我们可以发现,⼀个普通字符占⼀个字符的位置,但是打印⼀个汉字字符,占⽤2个字符的位置,那么我们如果 要在贪吃蛇中使⽤宽字符,就得处理好地图上坐标的计算。
此外,我们的VS2022是默认的正常模式,而我们的汉字是不包含在这里面的,所以我们需要将当地地区改为适应本地模式,于是我们需要使用 setlocale 函数来使我们的编译器符合我们的本地模式。
而为了使用 setlocale 我们需要包含头函数 #include<locale.h> ,setlocale 的源代码声明如下:setlocale,_wsetlocale | Microsoft Learn
char* setlocale (int category, const char* locale);
C标准给第⼆个参数仅定义了2种可能取值:“C” 和 “ ”。于是我们可以有以下两种写法:
setlocale(LC_ALL, "C");
//此时当地设置为“C”,库函数按正常方式执行,小数点是一个点
setlocale(LC_ALL, " ");
//切换到本地环境,这种模式下程序会适应本地环境
这时候我们写代码的必要条件已经做好了,接下来博主会在下一篇博客里给大家手撕一个贪吃蛇,敬请期待哦~
真正的幸运在等待着有资格享受的 ---------- 忒俄克里托斯
本篇博客也就到此为止了,送大家一碗鸡汤,勉励自己以及这世界上所有追逐梦想的赤子趁年华尚好努力提升自己,莫欺少年穷! 
相关文章:
C语言小游戏:贪吃蛇(游戏开发的环境和功能介绍)
❀❀❀ 文章由不准备秃的大伟原创 ❀❀❀ ♪♪♪ 若有转载,请联系博主哦~ ♪♪♪ ❤❤❤ 致力学好编程的宝藏博主,代码兴国!❤❤❤ 生命不停,学习不止。铁汁们,我是大伟,欢迎来到大伟的游戏时间,…...
ElementUI Form:InputNumber 计数器
ElementUI安装与使用指南 InputNumber 计数器 点击下载learnelementuispringboot项目源码 效果图 el-radio.vue (InputNumber 计数器)页面效果图 项目里el-input-number.vue代码 <script> export default {name: el_input_number,data() {re…...
apk反编译修改教程系列---修改apk的默认颜色 布局颜色 手机电脑同步演示【十】
往期教程: apk反编译修改教程系列-----修改apk应用名称 任意修改名称 签名【一】 apk反编译修改教程系列-----任意修改apk版本号 版本名 防止自动更新【二】 apk反编译修改教程系列-----修改apk中的图片 任意更换apk桌面图片【三】 apk反编译修改教程系列---简单…...
响应式开发如何设置断点,小屏幕界面该如何显示(有动图)
Hi,我是贝格前端工场,本期分享响应式开发,如何设置屏幕断点,pc页面布局到了移动端之后该如何布局的问题,微软也提供了设置屏幕断点的动图演示,非常直观。 一、什么是响应式开发,为何要设置屏幕断…...
Java基础 集合(二)List详解
目录 简介 数组与集合的区别如下: 介绍 AbstractList 和 AbstractSequentialList Vector 替代方案 Stack ArrayList LinkedList 前言-与正文无关 生活远不止眼前的苦劳与奔波,它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界…...
UE4运用C++和框架开发坦克大战教程笔记(十七)(第51~54集)
UE4运用C和框架开发坦克大战教程笔记(十七)(第51~54集) 51. UI 框架介绍UE4 使用 UI 所面临的问题以及解决思路关于即将编写的 UI 框架的思维导图 52. 管理类与面板类53. 预加载与直接加载54. UI 首次进入界面 51. UI 框架介绍 U…...
GaussDB新体验,新零售选品升级注入新思路【华为云GaussDB:与数据库同行的日子】
选品思维:低频VS高频 一个的商超,假设有50个左右的品类,每个品类下有2到10个不等的商品。然而如此庞大的商品,并非所有都是高频消费品。 结合自身日常的消费习惯,对于高频和低频的区分并不难。一般大型家电、高端礼盒…...
C语言问题汇总
指针 #include <stdio.h>int main(void){int a[4] {1,2,3,4};int *p &a1;int *p1 a1;printf("%#x,%#x",p[-1],*p1);} 以上代码中存在错误。 int *p &a1; 错误1:取a数组的地址,然后1,即指针跳过int [4]大小的字节…...
QT 的 blockSignals(true) 的作用范围
在 Qt 中,blockSignals 是一个用于控件的方法,它用于阻止控件发出的信号。如果你在一个 MainWindow 对象上调用 blockSignals(true),它会阻止该 MainWindow 对象发出的所有信号。 这意味着,如果 MainWindow 上有任何子控件&#…...
【C++私房菜】类和对象万字详解
目录 一、类与对象 1、类是什么 二、类和对象的基础知识 2.1 定义类:成员变量和成员函数 2.2 创建对象:实例化一个类的对象。 2.3对象的生命周期:构造函数和析构函数。 a. 构造函数 b. 析构函数 c.小结: 三、成员变量和…...
PDF下载添加水印和访问密码
下载接口 ApiOperation(value "下载文件-pdf", notes "下载文件pdf版", httpMethod "GET", response WebResult.class)RequestMapping(value "/downloadPdf", method RequestMethod.GET)public void downloadFilePdf(RequestPar…...
基于SSM+MySQL的的新闻发布系统设计与实现
目录 项目简介 项目技术栈 项目运行环境 项目截图 代码截取 源码获取 项目简介 新闻发布系统是一款基于Servletjspjdbc的网站应用程序,旨在提供一个全面且高效的新闻发布平台。该系统主要包括后台管理和前台新闻展示两个平台,涵盖了新闻稿件的撰写…...
记录首次使用yolov8-obb
1.数据格式 之前使用的数据格式是yolov5_obb的数据格式,然后需要转数据格式: 目前的数据只支持四个坐标点标注的数据,参考:If a corner of the rotate rectangle is out of the image range, How to annotate the image? Issu…...
深度学习环境配置:Anaconda 安装和 pip 源
conda是一种通用包管理系统,与pip的使用类似,环境管理则允许用户方便地安装不同版本的python并可以快速切换。 Anaconda则是一个打包的集合,里面预装好了conda、某个版本的python、众多packages、科学计算工具等等,就是把很多常用…...
100 个 NLP 面试问题
100 个 NLP 面试问题 一、 说明 对于技术磨练中,其中一项很酷的技能培训是提问。不知道答案并没有多大的错;错就错在不谷歌这些疑问。本篇就是在面试之前,您将此文档复制给自己,做一个系统的模拟实战。 二、经典NLP问题(共8题&a…...
C# OMRON PLC FINS TCP协议简单测试
FINS(factory interface network service)通信协议是欧姆龙公司开发的用于工业自动化控制网络的指令/响应系统。运用 FINS指令可实现各种网络间的无缝通信,包括用于信息网络的 Etherne(以太网),用于控制网络的Controller Link和SYSMAC LINK。…...
MQTT在linux下服务端和客户端的应用
MQTT(Message Queuing Telemetry Transport)是一种轻量级、开放标准的消息传输协议,设计用于受限设备和低带宽、不稳定网络的通信。 MQTT的一些关键特点和概念: 发布/订阅模型: MQTT采用发布/订阅(Publ…...
韦达定理用处多
文章目录 前言一、一元二次方程中根和系数之间的关系二、韦达定理的数学推导和作用1. 韦达定理的数学推导2. 韦达定理的作用 三、韦达定理的应用举例1. 解题示例12. 解题示例23. 解题示例34. 解题示例45. 解题示例56. 解题示例67. 解题示例7 总结 前言 韦达定理说明了一元n次方…...
Kotlin-类
构造函数 Java final File file new File("file.txt");Kotlin val file File("file.txt")类 Java public final class User { }Kotlin class User公开类 Java public class User { }Kotlin open class User属性类 Java final class User {pri…...
redis基本数据结构介绍
Redis(Remote Dictionary Server)是一个开源的高性能键值对数据库,它支持多种数据结构,包括字符串、哈希、列表、集合、有序集合等。这些数据结构为开发者提供了丰富的数据操作方式,使得Redis在缓存、消息队列、排行榜…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
