挑战!贪吃蛇小游戏的实现(1)

引言

相信大家都玩过贪吃蛇这个游戏!

玩家控制一个不断移动的蛇形角色,在一个封闭空间内移动。随着时间推进,这个蛇形角色会逐渐增长,通常是通过吞食屏幕上出现的物品(如点或者其他标志)来实现。每当贪吃蛇吃掉一个物品时,它就会变得更长一些。

目标是尽可能地让蛇增长而不撞击墙壁、障碍物或自己的身体部分。如果发生了这样的碰撞,则游戏结束。难度主要来源于两方面:一方面是由于贪吃蛇长度不断增加导致操作空间越来越小;另一方面则是速度可能会逐步提升,对玩家反应能力和策略规划提出了更高要求。

那么,我们能否使用C语言在Windows环境的控制台中模拟实现贪吃蛇小游戏呢~

答案是可以!

由于本次实现贪吃蛇会使用一些Win32 API的知识,所以我们先来学习一下Win32 API!

Win32 API

什么是Win32 API

Win32 API(Application Programming Interface)是微软Windows操作系统提供的一套核心接口,用于开发32位和64位的应用程序。这些API为程序员提供了访问Windows系统底层服务的方法,包括窗口管理、文件操作、设备输入输出、内存管理和进程线程控制等。

Win32 API可以分为几个不同的类别:

  1. 用户界面(User Interface)API:负责创建和管理窗口、对话框以及其他图形用户界面元素。例如CreateWindow()函数就是用来创建一个窗口。

  2. 图形设备接口(Graphics Device Interface, GDI)API:GDI APIs允许应用程序在屏幕上绘制图形,并处理字体和打印机输出。例如LineTo()函数可以画一条直线。

  3. 系统服务API:提供对系统级功能如注册表操作、事件日志记录等的访问。例如RegOpenKeyEx()函数可以打开注册表键值。

  4. 文件与I/O API:允许读写文件系统中的数据,以及与外部设备进行通信。例如ReadFile() 和 WriteFile() 函数可用于文件读写。

  5. 进程与线程管理API:控制进程和线程生命周期,实现多任务并发执行能力。CreateProcess() 可以启动新进程,而CreateThread() 会创建一个新线程。

  6. 网络服务API:支持网络通信功能,如TCP/IP连接、数据发送接收等。WSAStartup(), socket(), connect(), send(), recv() 是常见网络编程相关函数。

  7. 安全性API :涉及到身份验证、权限检查等安全相关功能。

  8. 多媒体API: 提供音频视频播放录制等多媒体处理能力。

1.控制台程序

我们可以使用cmd命令来设置控制台窗口的长度:比如设置控制台窗口大小为30行 100列

mode con cols=100 lines=30

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

title 贪吃蛇

这些能在控制台窗口执行的命令,也可以调用C语言函数system来执行

objectivec 复制代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
  system("mode con cols=100 lines=30");
  //设置控制台窗口大小 30行 100列
  system("title 贪吃蛇");
  //设置cmd窗口名称
  return 0;
}

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

COORD是Windows API中定义的一个结构体,表示一个字符在控制台屏幕上的坐标

objectivec 复制代码
typedef struct _COORD{
  SHORT x;
  SHORT Y;
}COORD,*PCOORD;

给坐标赋值(使用时要包含头文件windows.h)

COORD pos = {10,15};

3.GetStdHandle

句柄:这是一个抽象的概念,用于表示对资源或对象的引用,它通常是一个整数值或者指针,通过这个值可以访问到底层系统资源,如文件,窗口和数据库连接等。

GetStdHandle:是一个Windows API函数。它用于从一个特定的标准设备(标准输出,标准输入或标准错误)中获得一个句柄,使用这个句柄可以操作设备。

HANDLE GetStdHandle(DWORD nstdHandle);

下列代码用于获取标准输出的句柄

objectivec 复制代码
HANDLE houtput = NULL;
houtput = GetStdHandle(STD_OUTPUT_HANDLE);

4.GetConsoleCursorInfo

该函数检索有关控制台屏幕缓冲区的光标大小和可见性信息

BOOL WINAPI GetConsoleCursorInfo(

HANDLE hConsoleOutput,

PCONSOLE_CURSOR_INFO lpConsoleCursorInfo//是指向CONSOLE_CURSOR_INFO结构的指针,该结构接收有关主机游标的信息

);

objectivec 复制代码
HANDLE houtput = NULL;
houtput = GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出的句柄

CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(houtput,&CursorInfo);//获取控制台光标信息

5.CONSOLE_CURSOR_INFO

该结构体包含了有关控制台光标的信息,光标大小和可见性数据

objectivec 复制代码
typedef struct _CONSOLE_CURSOR_INFO{
  DWORN dwSize;
  BOOL  bVisible;
}CONSOLE_CURSOR_INFO,*PCONSOLE_CURSOR_INFO;
  • dwSize 由光标填充的字符单元格的百分比。光标的外观会变化,从完全填充单元格到单元底部的水平线条。此值介于1-100之间。
  • bVisible 游标的可见性。如果光标可见,此值为TRUE。
objectivec 复制代码
CursorInfo.bVisible =false;//隐藏控制台光标

6.SetConsoleCursorInfo

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

objectivec 复制代码
BOOL WINAPI SetConsoleCursorInfo{
  HANDLE hconsoleoutput,
  const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo
};
objectivec 复制代码
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);

CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(houtput,&CursorInfo);//获取控制台光标信息
CursorInfo.bVisible = false;//隐藏控制台光标
SetConsoleCursorInfo(houtput,&CursorInfo);//设置控制台光标状态

7.SetConsoleCursorPosition

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

objectivec 复制代码
BOOL WINAPI SetConsoleCursorPosition(
  HANDLE  hconsoleoutput,
  COORD pos

);
objectivec 复制代码
COORD pos = {10,5};
HANDLE houtput = NULL;
houtput = GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出的句柄
SetConsoleCursorPosition(houtput,pos);//设置标准输出上光标位置为pos

由此,我们可以封装一个设置光标位置的函数SetPos

objectivec 复制代码
void SetPos(short x,short y)
{
  COORD pos ={x,y};
  HANDLE houtput = NULL;
  houtput = GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出的句柄
  SetConsoleCursorPosition(houtput,pos);//设置光标位置
}

8.GetAsyncKeyState

该函数用于获取按键情况,GetAsyncKeyState的函数原型如下

SHORT GetAsyncKeyState(

int vKey;

);

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

GetAsyncKeyState的返回值为short类型,在上一次调用该函数后,如果返回的16位short数据中,最高位是1,说明按键的状态是按下,如果最高位是0,说明按键的状态是抬起;如果最低位被设置成1说明该按键被按过,否则为0

所以要判断一个按键是否被按过,我们可以检测该函数返回值的最低位是否为1

objectivec 复制代码
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1?1:0)

好啦!关于WIN32 API及相关函数的介绍就到这里啦,在下一篇博客中,我将详细实现贪吃蛇小游戏!防止迷路ovo请点赞收藏加关注哦~

相关推荐
小林熬夜学编程35 分钟前
【Linux网络编程】第十四弹---构建功能丰富的HTTP服务器:从状态码处理到服务函数扩展
linux·运维·服务器·c语言·网络·c++·http
Jackey_Song_Odd1 小时前
C语言 单向链表反转问题
c语言·数据结构·算法·链表
乐之者v1 小时前
leetCode43.字符串相乘
java·数据结构·算法
A懿轩A2 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
半盏茶香2 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
️南城丶北离3 小时前
[数据结构]图——C++描述
数据结构··最小生成树·最短路径·aov网络·aoe网络
✿ ༺ ོIT技术༻3 小时前
C++11:新特性&右值引用&移动语义
linux·数据结构·c++
字节高级特工3 小时前
【C++】深入剖析默认成员函数3:拷贝构造函数
c语言·c++
计算机学长大白4 小时前
C中设计不允许继承的类的实现方法是什么?
c语言·开发语言
XH华9 小时前
初识C语言之二维数组(下)
c语言·算法