大二必做项目贪吃蛇超详解之上篇win32库介绍

文章目录

  • 1. 游戏背景
  • 2. 游戏效果演示
  • 3. 项目目标
  • 4. 前置知识
  • 5. Win32 API
  • 5. 1 控制台程序(Console)
    • 5. 2 控制台屏幕上的坐标 `COORD`
    • 5. 3 GetStdHandle
    • 5. 4 GetConsoleCursorlnfo
      • 5. 4. 1 CONSOLE_CURSOR_INFO
      • 5. 4. 2 SetConsoleCursorlnfo
    • 5. 5 SetconsoleCursorPosition
    • 5. 6 GetAsyncKeyState


1. 游戏背景

贪吃蛇是久负盛名的游戏,它也和俄罗斯方块,扫雷等游戏位列经典游戏的行列。

2. 游戏效果演示

贪吃蛇演示视频

3. 项目目标

使用C语言在Windows环境的控制台中模拟实现经典小游戏贪吃蛇。

实现基本的功能:

  1. 贪吃蛇地图绘制
  2. (上、下、左、右方向键控制蛇的动作)
  3. 蛇吃食物
  4. 蛇撞墙死亡
  5. 蛇撞自身死亡
  6. 计算得分
  7. 再来一把
  8. 加速、减速
  9. 暂停游戏

4. 前置知识

C语言函数、结构体与枚举、动态内存管理、预处理指令、单链表、Win32 API(本文介绍)等(除了这些,还应该熟知C语言的基本语法,比如操作符什么的,就不一一列举了)。

5. Win32 API

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

win32API提供了非常多的接口以供使用,本博客只介绍在贪吃蛇游戏中会用到的接口。
win32API不同于C语言基础语法,大多都是封装好的函数,初次接触这样的开发可能会有些头晕,但这是向制作更复杂的项目的必经之路,也是学习更高级的语言的必然过程,需要尝试去接受。

5. 1 控制台程序(Console)

平常我们运行起来的黑框程序其实就是控制台程序
我们可以使用cmd命令来设置控制台窗口的长宽:设置控制台窗口的大小为30行,100列

mode con cols=100 lines=30

你可以在微软开发文档中获取更多mode命令。

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

title 贪吃蛇

你可以在微软开发文档中详细了解title命令。
这些能在控制台窗口执行的命令,也可以调用C语言函数system来执行。例如:

#include <stdio.h>
int main()
{ //设置控制台窗口的长宽:设置控制台窗口的大小,30行,100列system("mode con cols=100 lines=30");//设置cmd窗口名称system("title 贪吃蛇");getchar();	//让程序不要直接结束,才能看到窗口名称的改变return 0;
}

这样就能在游戏开始前固定窗口大小与名称了。
实例

补充:
本文代码均在cmd窗口中有效,如果你的编译器默认打开的不是cmd而是终端,可能会出现一些奇怪的问题,你可以按照下图方式修改:
1
2

5. 2 控制台屏幕上的坐标 COORD

COORDWindows API中定义的一个结构体,表示一个字符在控制台屏幕幕缓冲区上的坐标,坐标系(0,0)的原点位于缓冲区的顶部左侧单元格
1
COORD类型的声明:

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

给坐标赋值:

COORD pos = { 10,15 };

关于它的使用,我们在后文再提。

5. 3 GetStdHandle

GetStdHandle 是一个Windows API函数。它用于从一个特定的标准设备(标准输入、标准输出或标准错误)中取得一个句柄HANDLE,用来标识不同设备的数值,必须要有句柄我们才能对标准设备进行操作),使用这个句柄可以操作设备。

HANDLE GetStdHandle(DWORD nStdHandle);

使用示例:

//本代码用于获取标准输出流的句柄并存储在 houtput 中
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);

5. 4 GetConsoleCursorlnfo

GetConsoleCursorlnfo用于检索有关指定控制台屏幕缓冲区的光标大小和可见性的信息。

BOOL WINAPI GetConsoleCursorInfo(HANDLE hConsoleOutput, PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
);	//不要在意它的返回值类型,我们重点关注它的参数

PCONSOLE_CURSOR_INFO是指向 CONSOLE_CURSOR_INFO结构的指针,该结构接收有关主机游标(光标)的信息。

5. 4. 1 CONSOLE_CURSOR_INFO

CONSOLE_CURSOR_INFO这个结构体,包含有关控制台光标的信息

typedef struct _CONSOLE_CURSOR_INFO {DWORD dwSize;BooL bvisible;
}CONSOLE_CURSOR_INFO,*PCONSOLE_CURSOR_INFO;

dwSize由光标填充的字符单元格的百分比。此值介于1到100之间。光标外观会变化,范围从完全填充单元格到单元底部的水平线条。
bVisible游标的可见性。如果光标可见,则此成员为 true

CursorInfo.bVisible = false;//隐藏控制台光标

当然,直接写这个代码是无法生效的!需要配合GetConsoleCursorlnfo和下面的SetConsoleCursorlnfo使用。

5. 4. 2 SetConsoleCursorlnfo

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

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);	

这是设置控制台光标不可见的固定格式,不可修改!(自定变量名除外)

5. 5 SetconsoleCursorPosition

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

BOOL WINAPI SetConsoleCursorPosition(HANDLE hConsoleOutput,COORD pos
);

使用示例:

COORD pos = { 10, 5 };
//获取标准输出的句柄
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//设置标准输出上光标的位置为 pos
SetConsoleCursorPosition(hOutput, pos);

在贪吃蛇的项目中,我们会非常频繁地设置光标的位置,为了使用方便,我们可以封装一个函数来方便我们使用:

//设置光标的坐标
void SetPos(short x, short y)
{COORD pos = { x, y };//获取标准输出的句柄(用来标识不同设备的数值)HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//设置标准输出上光标的位置为 posSetConsoleCursorPosition(hOutput, pos);
}

这样,我们只需要传入x,y就可以很方便地设置光标的位置了。

5. 6 GetAsyncKeyState

GetAsyncKeystate用于2获取按键情况,它的函数原型如下:

SHORT GetAsyncKeyState(int vKey
);

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

GetAsyncKeyState 的返回值是short类型,在上一次调用 GetAsyncKeyState 函数后,如果返回的16位的short数据中,最高位是1,说明按键的状态是按下,如果最高是0,说明按键的状态是抬起,如果最低位被置为1则说明,该按键被按过,否则为0。如果我们要判断一个键是否被按过,可以检测GetAsyncKeyState返回值的最低值是否为1。

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

你可以使用这个宏来方便地判断这个键是否被按下,当然你也可以用函数,但是这样简单的逻辑并没有太大的必要去使用函数。
参考:虚拟键码(注意只有表格第一列有虚拟键值的键才能被这个接口检测)

实例:检测数字键

#include <stdio.h>
#include <windows.h>
#define KEY_PRESS(VK) ( (GetAsyncKeyState(VK) & 0x1) ? 1 : 0 )
int main()
{while (1){if (KEY_PRESS(0x30))		//0printf("0\n");else if (KEY_PRESS(0x31))	//1printf("1\n");else if (KEY_PRESS(0x32))	//2printf("2\n");else if (KEY_PRESS(0x33))	//3printf("3\n");else if (KEY_PRESS(0x34))	//4printf("4\n");else if (KEY_PRESS(0x35))	//5printf("5\n");else if (KEY_PRESS(0x36))	//6printf("6\n");else if (KEY_PRESS(0x37))	//7printf("7\n");else if (KEY_PRESS(0x38))	//8printf("8\n");else if (KEY_PRESS(0x39))	//9printf("9\n");}return 0;
}

这个代码的功能就是在按下键盘上方的数字(小数字键盘无效)时,在屏幕上打印一个对应的数字,注意全程没有使用scanfgetchar

贪吃蛇所需要用到的win32库基本只涉及到这些,下篇博客将开始正式设计贪吃蛇游戏。

谢谢你的阅读,喜欢的话来个点赞收藏评论关注吧!
我会持续更新更多优质文章

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux(面试篇)

目录 什么是Linux 什么是Linux内核&#xff1f; Linux的基本组件是什么&#xff1f; Bash和Dos之间基本区别是什么&#xff1f; 什么是Root账户 什么是Bash? 什么时CLI? Linux的目录结构时怎样的&#xff1f; 什么是硬链接和软链接&#xff1f; 什么叫CC攻击&#…

【项目日记】高并发内存池 ---项目介绍及组件定长池的实现

余生还长&#xff0c;你别慌&#xff0c;也别回头&#xff0c;别念旧. --- 余华 --- 1 高并发内存池简介 高并发内存池项目是实现一个高并发的内存池&#xff0c;他的原型是google的一个开源项目tcmalloc&#xff0c;tcmalloc全称Thread-Caching Malloc&#xff0c;即线程缓存…

RocketMQ Dashboard

rocketmq-dashboard是一个可视化查看和管理RocketMQ消息队列的工具 官方地址&#xff1a;RocketMQ Dashboard | RocketMQ 1、点击下载源码 2、下载并解压&#xff0c;切换至源码目录rocketmq-dashboard-1.0.0 3、修改配置文件 4、编译 rocketmq-dashboard打成jar包 &#xf…

MySQL中的回表查询、索引覆盖、索引下推

本文重点介绍索引中的常见概念&#xff1a;回表查询、索引覆盖、索引下推 一、回表查询 我们首先理解&#xff1a;在InnoDB存储引擎中&#xff0c;根据索引的存储形式&#xff0c;又可以分为以下两种&#xff1a; 分类含义特点聚集索引 (Clustered Index)将数据存储与索引放到…

leetcode 438.找到字符串中所有字母异位词

目录 题目描述 示例1&#xff1a; 示例2&#xff1a; 提示&#xff1a; 解题思路 Collections库 介绍 滑动窗口法 概念 应用场景及特点&#xff1a; 思路 流程展示 代码 复杂度分析 题目描述 给定两个字符串s和p&#xff0c;找到s中所有p的异位词的子串&#xf…

cdga|让数据治理真正内嵌于企业本身,释放企业数字化建设的最大价值

在当今这个数据驱动的时代&#xff0c;企业数据已成为最宝贵的资产之一&#xff0c;它不仅记录着企业的运营轨迹&#xff0c;更是指导决策、优化流程、创新产品与服务的关键力量。然而&#xff0c;要充分发挥数据的潜力&#xff0c;实现数字化转型的深度与广度&#xff0c;就必…

SAP 有趣的‘bug‘ 选择屏幕输入框没了

如下代码将会输出一个P_U的字段 PARAMETERS p_u TYPE string VISIBLE LENGTH 12 MEMORY ID m1.AT SELECTION-SCREEN OUTPUT.LOOP AT SCREEN.IF screen-name P_U.screen-invisible 1.MODIFY SCREEN.ENDIF.ENDLOOP. 如果我们给这个字段设置一个默认值&#xff0c;参考如下代码…

医疗器械法规标准相关资料

文章目录 前言如何查找法规文件与标准1. 法规清单2. 医疗器械法规文件汇编常用链接常见网站微信公众号前言 在前文 医疗器械软件相关法律法规与标准 中介绍了在软件设计过程常见的法规与标准,并给出部分标准如何查找和下载的方法,但是上文中列举的部分不全面,真实在产品设计…

集合及数据结构第十节(上)————优先级队列,堆的创建、插入、删除与用堆模拟实现优先级队列

系列文章目录 集合及数据结构第十节&#xff08;上&#xff09;————优先级队列&#xff0c;堆的创建、插入、删除与用堆模拟实现优先级队列 优先级队列&#xff0c;堆的创建、插入、删除与用堆模拟实现优先级队列 优先级队列的概念堆的概念堆的存储方式堆的创建变量的作…

审计发现 FBI 的数据存储管理存在重大漏洞

据The Hacker News消息&#xff0c;美国司法部监察长办公室 &#xff08;OIG&#xff09; 的一项审计发现&#xff0c; FBI 在库存管理和处置涉及机密数据的电子存储媒体方面存在“重大漏洞”。 OIG 的审计显示&#xff0c;FBI 对包含敏感但未分类 &#xff08;SBU&#xff09…

Nvidia驱动莫名其妙不好使了?nvidia-smi报错?如何解决?已解决!!

文章目录 一、报错提示二、解决方案2.1 原因1的解决办法2.2 原因2的解决方案 一、报错提示 Ubuntu20.04出现Failed to initialize NVML: Driver/library version mismatch问题NVIDIA-SMI has failed because it couldn‘t communicate with the NVIDIA driver. 二、解决方案 …

论文翻译:Multi-step Jailbreaking Privacy Attacks on ChatGPT

Multi-step Jailbreaking Privacy Attacks on ChatGPT https://arxiv.org/pdf/2304.05197 多步骤越狱隐私攻击对ChatGPT的影响 文章目录 多步骤越狱隐私攻击对ChatGPT的影响摘要1 引言2 相关工作3 对ChatGPT的数据提取攻击3.1 数据收集3.2 攻击制定3.3 从ChatGPT中提取私人数据…

网上商城|基于SprinBoot+vue的分布式架构网上商城系统(源码+数据库+文档)

分布式架构网上商城系统 目录 基于SprinBootvue的分布式架构网上商城系统 一、前言 二、系统设计 三、系统功能设计 5.1系统功能模块 5.2管理员功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍…

Mybatis-plus 创建自定义 FreeMarker 模板详细教程

FreeMarker 自定义模板官方步骤 网址&#xff1a;https://baomidou.com/reference/new-code-generator-configuration/#%E6%A8%A1%E6%9D%BF%E9%85%8D%E7%BD%AE-templateconfig &#xff08;页面往最下面拉为自定义模板相关内容&#xff09; 创建自定义FreeMarker 模板及使用…

Github文件夹重命名|编程tips·24-08-22

小罗碎碎念 这篇推文来解决一个问题&#xff0c;**我上传代码带Github以后&#xff0c;想要修改文件夹的名称怎么办&#xff1f;**例如&#xff0c;我要将文件夹24-08-22修改为联接散点图&#xff5c;24-08-22&#xff0c;可以遵循以下操作。 一、配置SSH 先登录github&#x…

一键生成原创文案的app有哪些?6款文案生成器值得分享

在这个信息爆炸的时代&#xff0c;文案创作的需求无处不在。为了提高文案创作的效率和质量&#xff0c;一键生成原创文案的app有哪些呢&#xff1f;对于这个问题&#xff0c;我们可以从市面上的文案生成器下手&#xff0c;因为文案生成器可以高效率的为创作者生产各种类型的文案…

韩语每日一句柯桥学韩语韩语零基础入门外贸韩语口语

韩语每日一词打卡&#xff1a;얹혀살다[언처살다]【动词】寄生,寄居。 原文:남의 집에 얹혀살지 말고 어렵더라도 직접 숙소를 구해야지. 意思&#xff1a;不要在别人家里寄居&#xff0c;哪怕困难也是要自己找一个住所。 【原文分解】 1、어렵다[어렵따]困难 2、직접[15857575…

wxpython Scintilla styledtextctrl滚动条拖到头文本内容还有很多的问题

wxpython Scintilla styledtextctrl滚动条拖到头文本内容还有很多的问题 使用wxpython Scintilla styledtextctrl&#xff0c;滚动条不自动更新 滚动条拖到头文本内容还有很多&#xff0c;如下&#xff1a; 以下是拖到最后的状态&#xff1a; 明显看出下图的滚动条的格子比…

手机谷歌浏览器怎么用

谷歌浏览器不仅在PC端受欢迎&#xff0c;在移动端也是广泛应用的。为了帮助大家更好的理解和使用手机谷歌浏览器&#xff0c;本文将详细介绍如何使用手机谷歌浏览器&#xff0c;对这款浏览器感到陌生的话就快快学起来吧。&#xff08;本文由https://chrome.cmrrs.com/站点的作者…

STM32——PWR电源控制的低功耗模式

1、理论知识 本节主要学习配置低功耗模式&#xff1a;防止在空闲时候耗电&#xff08;关闭/唤醒哪些硬件很重要&#xff09; 虽然STM32外部需要使用3.3V供电&#xff0c;但内部核心电路CPU、外设和存储器使用1.8V供电即可&#xff0c;这3者需要与外界交流时才需要3.3V供电 从上…