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

news2024/11/16 7:50:13

文章目录

  • 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);
	//设置标准输出上光标的位置为 pos
	SetConsoleCursorPosition(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))		//0
			printf("0\n");
		else if (KEY_PRESS(0x31))	//1
			printf("1\n");
		else if (KEY_PRESS(0x32))	//2
			printf("2\n");
		else if (KEY_PRESS(0x33))	//3
			printf("3\n");
		else if (KEY_PRESS(0x34))	//4
			printf("4\n");
		else if (KEY_PRESS(0x35))	//5
			printf("5\n");
		else if (KEY_PRESS(0x36))	//6
			printf("6\n");
		else if (KEY_PRESS(0x37))	//7
			printf("7\n");
		else if (KEY_PRESS(0x38))	//8
			printf("8\n");
		else if (KEY_PRESS(0x39))	//9
			printf("9\n");
	}
	return 0;
}

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

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

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

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

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

相关文章

“汤姆猫除了不会捉杰瑞啥都会”之作为Web服务器,tomcat的常用部署方式 (Tomcat+memcached实现高可用)

目录 企业级WEB应用服务器TOMCAT一、tomcat的功能介绍1.1 安装 Tomcat1.2 tomcat的文件结构和组成1.3 生成tomcat的启动文件 二、结合反向代理实现tomcat部署2.1 常见部署方式介绍2.2 利用 nginx 反向代理实现2.3 实现tomcat中的负载均衡2.3.1 HTTP的无状态&#xff0c;有连接和…

Linux驱动学习之中断与等待队列

本篇分为设备树部分和API接口部分 设备树 想要使用中断&#xff0c;设备树中需要有两个属性&#xff1a; interrupts // 表示要使用哪一个中断, 中断的触发类型等等。 interrupt-parent // 这个中断要接到哪一个设备去? 即父中断控制器是谁 父中…

一种更快成像的新技术

斯旺西大学&#xff08;Swansea University&#xff09;的研究人员为中性原子束显微镜创造了一种新的成像方法&#xff0c;可大大加快显微镜图像的获取速度。中性原子束显微镜已成为科学研究的一个重点&#xff0c;因为它能够对商用显微镜无法成像的表面进行成像&#xff0c;例…

mysql集群从零开始搭建

文章目录 MySQL集群linux下部署mysqlmysql主从复制master配置配置slave新的slave加入延迟复制慢查询多线程原理 半同步模式原理gat模式启动半同步模式 mysql高可用之组复制&#xff08;MGR&#xff09;实现mysql组复制 mysql路由具体实现 mysql高可用之MHAMHA部署实施安装MHA软…

Codeforces Round 968 (Div. 2 ABCD1D2题) 视频讲解

A. Turtle and Good Strings Problem Statement Turtle thinks a string s s s is a good string if there exists a sequence of strings t 1 , t 2 , … , t k t_1, t_2, \ldots, t_k t1​,t2​,…,tk​ ( k k k is an arbitrary integer) such that: k ≥ 2 k \ge 2 k≥…

接口自动化测试利器,使用Rest Assured进行REST API测试

我们在做接口测试时&#xff0c;一般在代码中会使用HttpClient&#xff0c;但是HttpClient相对来讲还是比较麻烦的&#xff0c;代码量也相对较多&#xff0c;对于新手而言上手会比较难一点&#xff0c;今天我们来看下另一个接口测试工具包REST Assured REST Assured是一个流行…

Blazor官方文档学习记录

Blazor官方文档学习记录 1 官方文档2 Blazor教程-生成首个应用3 项目结构4 基础知识4.1 生态4.2 Razor组件指令顺序4.3 Razor组件的初始化方法 5 注意 1 官方文档 https://dotnet.microsoft.com/zh-cn/apps/aspnet/web-apps/blazor2 Blazor教程-生成首个应用 https://dotnet.…

Python | Linux | 解析Himawari-8/9 | Standard Data

写作前面 之前一个相关的工作需要解析Himawari-8/9 Standard Data文件&#xff0c;因为他是二进制的&#xff0c;之前没有处理过&#xff0c;导致完全摸不着头脑。在网上找了中英文搜索找了好久&#xff0c;虽然也找到了公开的解析代码&#xff0c;但是放在自己的数据这感觉总是…

趣味算法------猴子吃桃(循环,递归双重解法)

题目描述 猴子第一天摘下若干个桃子&#xff0c;当天吃了一半&#xff0c;后面又多吃一个。第二天早上又将剩下的桃子吃掉一半&#xff0c;又多吃了一个。后面每天猴子都吃了前一天剩下的一半零一个。到第十天想再吃时&#xff0c;只剩下一个桃子。求第一天共摘了多少桃子。 …

鸿蒙(API 12 Beta3版)【获取音视频元数据】音频播放与录制

使用AVMetadataExtractor可以实现从原始媒体资源中获取元数据&#xff0c;本开发指导将以获取一个音频资源的元数据作为示例&#xff0c;向开发者讲解AVMetadataExtractor元数据相关功能。视频资源的元数据获取流程与音频类似&#xff0c;由于视频没有专辑封面&#xff0c;所以…

【中仕公考怎么样】公务员备考小建议

2025年国考在即&#xff0c;掌握正确的备考方法很重要&#xff01;中仕为大家简单分享4点小技巧。 1. 在提升行测分数时&#xff0c;可以采用大量的练习题、整理题以及关注往年核心考点的方式。无论处于准备过程的哪一阶段&#xff0c;对各类题型进行深入分析并掌握相应的解题…

C++ | Leetcode C++题解之第373题查找和最小的K对数字

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {int m nums1.size();int n nums2.size();auto count [&](int target){long long …

怎么用AI生成PPT演讲稿?5个方法教你快速生成

想象一下&#xff0c;你正在准备一场关于“墨西哥是如何走到今天这一步的”演讲&#xff0c;而你却苦于如何将复杂的历史背景、经济变迁以及文化特色等内容有机地整合进一份PPT中。 这时候&#xff0c;一款好的AI自动生成PPT的工具就能派上用场了。它不仅能够帮助你快速构建起…

C# 使用 WinForm MDI 模式管理多个子窗体程序的详细步骤

前言 嗨&#xff0c;各位码农们&#xff01;今天我们要来聊聊如何在 C# 的 WinForms 应用程序中用 MDI&#xff08;Multiple Document Interface&#xff09;模式来优雅地管理多个子窗体。 如果你曾经对着一堆乱七八糟的窗体不知所措&#xff0c;或者想要让你的应用程序看起来…

基于SpringBoot的线上教学平台系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言 Java 数据库 MySQL 技术 SpringBoot框架&#xff0c;Java语言 工具 IDEA/Eclipse、Navicat、Maven 系统展示 首页 管理员功能模块 学员功能模块 前台首页…

16行为型设计模式——策略模式

一、策略模式简介 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一系列的算法&#xff0c;将每一个算法封装起来&#xff0c;并使它们可以相互替换。具体的算法选择交由客户端决定&#xff0c;即不同的算法可以在运行时动态地&a…

后端微服务架构:构建分布式博客系统

后端微服务架构&#xff1a;构建分布式博客系统 在当今的软件开发领域&#xff0c;微服务架构已经成为构建可扩展、灵活且易于维护的应用程序的主流选择。本文将探讨如何利用微服务架构来设计和实现一个分布式的博客系统。 1. 微服务架构简介 微服务架构是一种将应用程序分解…

练习题 期望dp

题目 分析&#xff1a; 首先注意到期望有线性性&#xff1a; E ( a b ) E ( a ) E ( b ) E(ab)E(a)E(b) E(ab)E(a)E(b)&#xff0c;其中 a a a、 b b b不要求相互独立。 因为网上很多地方的证明不严谨&#xff0c;所以这里证明一下&#xff1a; E ( a b ) ∑ i i ⋅ P …

C语言基础(十八)

1、共用体&#xff08;Union&#xff09;是一种特殊的数据类型&#xff0c;也被称为联合体&#xff0c;它允许在相同的内存位置存储不同的数据类型&#xff0c;每次只能存储其中一种类型的值。共用体是一种数据结构&#xff0c;多个不同类型的变量能够共享同一段内存空间。在C语…

OpenAI推出新功能:GPT-4o正式上线微调功能,限时免费!

GPT-4o正式上线微调功能&#xff0c;限时免费&#xff01; 每个组织每天可以免费获得多达100万个训练token&#xff0c;活动将持续到9月23日。 这意味着开发者们现在可以利用自定义数据集对GPT-4o进行微调&#xff0c;从而以较低的成本构建自己的应用程序。 据悉&#xff0c;G…