C语言小游戏:贪吃蛇(游戏开发的环境和功能介绍)

news2024/11/27 6:26:15

❀❀❀ 文章由@不准备秃的大伟原创 ❀❀❀

♪♪♪ 若有转载,请联系博主哦~ ♪♪♪

❤❤❤ 致力学好编程的宝藏博主,代码兴国!❤❤❤

         生命不停,学习不止。铁汁们,我是大伟,欢迎来到大伟的游戏时间,今天带大家来玩一款几乎是所有人童年的记忆中的一款经典的不能再经典的游戏:贪吃蛇!

        当然了,在玩游戏前,我们还是要先把游戏写出来啦!○( ^皿^)っHiahiahia…

45942329dfab404885982806120a8c45.png

        废话不多说,在开始游戏前,有些知识是希望大家了解的(因为博主也不是很懂,所以只能理解了,QWQ) 。

        由于我们的贪吃蛇游戏是在我们windows电脑的控制台上实现的,所以我想带大家了解一下Win32 API:

        我们的小度娘给Win32 API的介绍是:

  Windows这个多作业系统除了协调应⽤程序的执⾏、分配内存、管理资源之外,它同时也是⼀个很⼤ 的服务中⼼,调⽤这个服务中⼼的各种服务(每⼀种服务就是⼀个函数),可以帮应⽤程序达到开启 视窗、描绘图形、使⽤周边设备等⽬的,由于这些函数服务的对象是应⽤程序(Application),所以便 称之为Application Programming Interface,简称 API 函数。WIN32 API也就是Microsoft Windows 32位平台的应⽤程序编程接⼝。

         听起来很高级是吧~嗯,雀食蛮高级的,但是作为我们使用的人来说并不需要了解这么多,会用就好了,对吧?

        首先,不知道有没有铁汁的VS操作台是和大伟一样是这样的?->59f768a6ad894e0abbb68d05742dcba0.png

        上面这个窗口其实是VS的操作台,而我们需要的是我们电脑的Windows操作台,该怎么切换呢?其实很简单:     768b918ef74546899fab76b3f1b075f6.png

a186ba6d259f440287fda959ba780e75.png         这样子就切换成功了,大家来看一看效果:1f50e38c1ead43f58350d63a6492e97f.png

        是不是瞬间就有玩游戏的感觉了?哈哈 (^▽^ )

        那这个时候就有铁汁好奇了,说:“大伟啊,你这个运行框的名字是‘贪吃蛇’,而且屏幕上有一串文字,窗口大小也和我的不一样,怎么回事啊?” ,诶,别急嘛,接下来就会教你滴~

        一. 设置控制台:

我们可以使⽤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轴,从上到下依次增⻓08279dd84e744df7929da4985cf86a99.png

        在游戏地图上,我们打印墙体使⽤宽字符:□,打印蛇使⽤宽字符●,打印⻝物使⽤宽字符★         普通的字符是占⼀个字节的,这类宽字符是占⽤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, " ");
//切换到本地环境,这种模式下程序会适应本地环境

        这时候我们写代码的必要条件已经做好了,接下来博主会在下一篇博客里给大家手撕一个贪吃蛇,敬请期待哦~

        真正的幸运在等待着有资格享受的 ---------- 忒俄克里托斯

        本篇博客也就到此为止了,送大家一碗鸡汤,勉励自己以及这世界上所有追逐梦想的赤子趁年华尚好努力提升自己,莫欺少年穷!  829e591a7798414fa84504131fe672c5.jpeg

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1433115.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【论文阅读笔记】InstantID : Zero-shot Identity-Preserving Generation in Seconds

InstantID:秒级零样本身份保持生成 理解摘要Introduction贡献 Related WorkText-to-image Diffusion ModelsSubject-driven Image GenerationID Preserving Image Generation Method实验定性实验消融实验与先前方法的对比富有创意的更多任务新视角合成身份插值多身份区域控制合…

【遥感入门系列】遥感电磁辐射与遥感过程

遥感电磁辐射是比较难理解也是非常重要的内容&#xff0c;对于一般学习遥感专业的人来说&#xff0c;只需要学习个大概&#xff0c;这个大概主要包括你需要理解几个概念以及能从电磁辐射原理上解释一些遥感现象&#xff0c;进而为遥感过程的理解打下一个基础&#xff0c;如果你…

85.如何设计高并发系统(缓存、限流、熔断、降级)

文章目录 一&#xff1a;简介二&#xff1a;什么是高并发1、高并发的定义2、高并发的特点3、高并发场景和应用4、高并发的影响 三&#xff1a;高并发应对策略四&#xff1a;缓存1、浏览器缓存2、客户端缓存3、CDN缓存4、反向代理缓存5、本地缓存6、分布式缓存7、缓存问题8、缓存…

【代码随想录-哈希表】两个数组的交集

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

STM32搭建开发环境

常用开发工具简介 集成开发环境 MDK&#xff1a;全名RealViewMDK&#xff0c;是Keil公司&#xff08;已被ARM收购的&#xff09;一款集成开发环境&#xff0c;界面美观&#xff0c;简单易用&#xff0c;是STM32最常用的集成开发环境EWARM&#xff1a;IAR公司的一款集成开发环…

Go语言Gin框架安全加固:全面解析SQL注入、XSS与CSRF的解决方案

前言 在使用 Gin 框架处理前端请求数据时&#xff0c;必须关注安全性问题&#xff0c;以防范常见的攻击。本文将探讨 Gin 框架中常见的安全问题&#xff0c;并提供相应的处理方法&#xff0c;以确保应用程序的稳健性和安全性。 处理前端请求数据时&#xff0c;确保应用程序的…

MFC结构体写入文件和读取

先定义一个结构体&#xff1b; struct myTxc { char c; CString name; int value; } txc; 读和写的菜单代码&#xff1b; void CjgtrwView::On32771() {// TODO: 在此添加命令处理程序代码CFile file(_T("test1.txt"), CFile::modeCreate | CFile::mod…

【Java 数据结构】String进阶

字符串常量池 1. 创建对象的思考2. 字符串常量池(StringTable)3. 再谈String对象创建 1. 创建对象的思考 下面两种创建String对象的方式相同吗&#xff1f; public static void main(String[] args) {String s1 "hello";String s2 "hello";String s3 …

Coil:Android上基于Kotlin协程的超级图片加载库

Coil&#xff1a;Android上基于Kotlin协程的超级图片加载库 1. coil简介 在当今移动应用程序的世界中&#xff0c;图片加载是一个不可或缺的功能。为了让应用程序能够高效地加载和显示图片&#xff0c;开发人员需要依赖于强大的图片加载库。而今天&#xff0c;我将向大家介绍…

SolidWorks 2023 使用操作流程

1. 把头 1.1. 新建零件 1.2. 新建草图 1.3. 拉升凸台 1.4. 等距实体 切换到锤头&#xff0c;新建草图&#xff0c;等距实体1mm 1.5. 拉升凸台 将上一个步骤的草图&#xff0c;进行特征拉升 1.6. 镜像处理 1.7. 圆角处理 1.8. 绘制凹槽 在锤子的侧面绘制草图 1.9. 挖出把手孔…

微信小程序课设(基于云开发)

微信小程序通过Laf云平台接入ChatGPT实现聊天&#xff0c;回答方式采用流式回答。 以下是图片展示其页面 回答次数通过卡密兑换 以下是对话页面的代码 <!--pages/content/content.wxml--><view class"container"><view class"div" hidde…

服务器使用过程中遇到常见故障及解决方案(包括蓝屏死机、无法删除的文件如何清理、网络卡、服务器连接不上等)

互联网时代&#xff0c;服务器的安全性和稳定性尤为重要&#xff0c;支撑着整个互联网行业的信息和数据安全。最近经常有客户咨询服务器的日常故障排除方法。由于服务器复杂的硬件结构和繁琐的运行原理&#xff0c;经常会出现这样那样的问题&#xff0c;有时即使是最小的问题也…

Redis -- set集合

挑战自己&#xff0c;每天进步一点点&#xff0c;成就将属于不停止脚步的你。 目录 Redis集合&#xff1f; 集合基本命令 sadd smembers sismember scard spop srandmember smove srem 集合间操作 sinter sinterstore sunion sdiff sdiifstore Redis集合&#…

Apple Vision Pro:新的隐私噩梦?

长期以来&#xff0c;苹果被誉为最注重隐私的科技公司之一&#xff0c;但如今&#xff0c;凭借售价 3499 美元的 Vision Pro&#xff0c;苹果可能已经打造出了一款终极监控机器。 作为苹果首款头戴式“空间计算”显示设备&#xff0c;号称将打造数字世界与物理世界交汇的新空间…

如何在本地部署chatGLM3

文章目录 1. 参考2. ChatGLM3 介绍3. 本地运行3.1 硬件配置3.2 下载ChatGLM3代码3.3 下载需要加载的模型3.4 运行大模型3.4.1 ChatGLM3目录介绍3.4.2 安装依赖3.4.2 综合demo演示3.4.3 启动对话模式工具模式代码解释器 4. 总结 前面一章节有讲到 基于MacBook Pro M1芯片运行ch…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之MenuItemGroup组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之MenuItemGroup组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、MenuItemGroup组件 该组件用来展示菜单MenuItem的分组。 子组件 无 接…

一次Kubernetes Pod内存异常导致的测试环境耗时异常问题排查过程

概述 在使用公司内部后台系统测试环境时发现一个请求加载慢的问题&#xff0c;简简单单的列表&#xff0c;查询MongoDB数据库&#xff0c;测试环境不过几百上千条数据而已&#xff0c;请求耗时居然高达5~6秒&#xff1a; 作为对比&#xff0c;生产环境的请求响应截图如下&…

flask+vue+python跨区通勤人员健康体检预约管理系统

跨区通勤人员健康管理系统设计的目的是为用户提供体检项目等功能。 与其它应用程序相比&#xff0c;跨区通勤人员健康的设计主要面向于跨区通勤人员&#xff0c;旨在为管理员和用户提供一个跨区通勤人员健康管理系统。用户可以通过系统及时查看体检预约等。 跨区通勤人员健康管…

Leetcode834. 树中距离之和

Every day a Leetcode 题目来源&#xff1a;834. 树中距离之和 解法1&#xff1a;换根 DP 题解&#xff1a;【图解】一张图秒懂换根 DP&#xff01;&#xff08;Python/Java/C/Go/JS&#xff09; 暴力做法是&#xff0c;以点 i 为为树根&#xff0c;从 i 出发对树进行深度…

【MATLAB源码-第135期】基于matlab的变色龙群优化算法CSA)机器人栅格路径规划,输出做短路径图和适应度曲线。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 变色龙群优化算法&#xff08;Chameleon Swarm Algorithm&#xff0c;CSA&#xff09;是一种新颖的群体智能优化算法&#xff0c;受到自然界中变色龙捕食和社交行为的启发。变色龙以其独特的适应能力而著称&#xff0c;能够根…