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

2024-08-26 21:20

本文主要是介绍大二必做项目贪吃蛇超详解之上篇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库基本只涉及到这些,下篇博客将开始正式设计贪吃蛇游戏。

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

这篇关于大二必做项目贪吃蛇超详解之上篇win32库介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1109719

相关文章

python管理工具之conda安装部署及使用详解

《python管理工具之conda安装部署及使用详解》这篇文章详细介绍了如何安装和使用conda来管理Python环境,它涵盖了从安装部署、镜像源配置到具体的conda使用方法,包括创建、激活、安装包... 目录pytpshheraerUhon管理工具:conda部署+使用一、安装部署1、 下载2、 安装3

Python进阶之Excel基本操作介绍

《Python进阶之Excel基本操作介绍》在现实中,很多工作都需要与数据打交道,Excel作为常用的数据处理工具,一直备受人们的青睐,本文主要为大家介绍了一些Python中Excel的基本操作,希望... 目录概述写入使用 xlwt使用 XlsxWriter读取修改概述在现实中,很多工作都需要与数据打交

详解Java如何向http/https接口发出请求

《详解Java如何向http/https接口发出请求》这篇文章主要为大家详细介绍了Java如何实现向http/https接口发出请求,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用Java发送web请求所用到的包都在java.net下,在具体使用时可以用如下代码,你可以把它封装成一

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

java脚本使用不同版本jdk的说明介绍

《java脚本使用不同版本jdk的说明介绍》本文介绍了在Java中执行JavaScript脚本的几种方式,包括使用ScriptEngine、Nashorn和GraalVM,ScriptEngine适用... 目录Java脚本使用不同版本jdk的说明1.使用ScriptEngine执行javascript2.

mac中资源库在哪? macOS资源库文件夹详解

《mac中资源库在哪?macOS资源库文件夹详解》经常使用Mac电脑的用户会发现,找不到Mac电脑的资源库,我们怎么打开资源库并使用呢?下面我们就来看看macOS资源库文件夹详解... 在 MACOS 系统中,「资源库」文件夹是用来存放操作系统和 App 设置的核心位置。虽然平时我们很少直接跟它打交道,但了

关于Maven中pom.xml文件配置详解

《关于Maven中pom.xml文件配置详解》pom.xml是Maven项目的核心配置文件,它描述了项目的结构、依赖关系、构建配置等信息,通过合理配置pom.xml,可以提高项目的可维护性和构建效率... 目录1. POM文件的基本结构1.1 项目基本信息2. 项目属性2.1 引用属性3. 项目依赖4. 构

Rust 数据类型详解

《Rust数据类型详解》本文介绍了Rust编程语言中的标量类型和复合类型,标量类型包括整数、浮点数、布尔和字符,而复合类型则包括元组和数组,标量类型用于表示单个值,具有不同的表示和范围,本文介绍的非... 目录一、标量类型(Scalar Types)1. 整数类型(Integer Types)1.1 整数字

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1