贪吃蛇---C语言---详解

引言

C语言已经学了不短的时间的,这期间已经开始C++和Python的学习,想给我的C语言收个尾,想起了小时候见过别人的老人机上的贪吃蛇游戏,自己父母的手机又没有这个游戏,当时成为了我的一大遗憾,这两天发现C语言实现这个项目似乎并不难,于是查了一些WindowsAPI的控制台函数,实现了这一游戏。如果你觉得你的C语言基础语法学的差不多了,又想实现贪吃蛇这样一个小游戏,那么就跟我一起来实现它吧。下面是最终成品的样子:

本贪吃蛇是用控制台实现,其中¥是贪吃蛇的食物,⚪是贪吃蛇,■是墙体。

Win32 API

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

控制台程序

平常我们运行起来的黑框其实是就是控制台程序

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

mode con cols=100 lines=30

同时也可以通过命令修改窗口的名字:

title 贪吃蛇

这里注意一下,在改名字之后加一个getchar()保证程序处在运行状态,这样才能正确观察到要改后的名字。

这些能在控制台窗口执行的命令,像我上方图片中的代码一样,可以用C语言函数system来执行。

代码放在下面:

#include<stdlib.h>
int main()
{
	system("mode con cols=100 lines=30");//设置窗口大小
	system("title 贪吃蛇");//改窗口标题
	getchar();
	return 0;
}

这里注意一下system的头文件是

#include <stdlib.h>

控制台上的坐标COORD

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

typedef struct _COORD{
    SHORT x;
    SHORT y;
}COORD, *PCOORD;

其中x轴和y轴如图

同时可以给上方结构体(坐标)赋值:

COORD pos = {10,15};

GetStdHandle

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

HANDLE GetStdHandle(DWORD nStdHandle);//函数的参数为标准设备

句柄是什么?

句柄相当于一个操作工具,你可以通过操作某设备的句柄去获得和修改某标准设备的信息

实例(获得句柄)

HANDLE hOutput = NULL;
//获取标准输出的句柄(用来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);

GetConsoleCursorInfo

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

BOOL WINAPI GetConsoleInfo(
    HANDLE hConsoleOutput,
    PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
);

实例:

HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值) 
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息 
//通过传CursorInfo的地址并通过函数将当前光标信息传给CursorInfo

CONSOLE_CURSOR_INFO

在上一份代码中CursorInfo,里面存的是光标信息,类型是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; //隐藏控制台光标 

SetConsoleCursorInfo

上方的GetConsoleCursorInfo是通过函数获取光标信息,这次的函数是通过函数实在改变控制台光标信息,下面是本函数声明

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);//设置控制台光标状态 

SetConsoleCursorPosition

设置指定控制台缓冲区的光标位置,我们可以将坐标信息放到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);
//通过以上代码可以将光标设置到10 5 位置上

看到这里,我们是否可以考虑封装一个函数,可以专门通过传入坐标来控制光标位置,于是封装了一个这样的函数Setpos

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

GetAsyncKeyState

这个函数用于获取按键情况,原型如下:

SHORT GetAsyncKeyState(
 int vKey
);

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

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

如果我们要判断一个按键是否被按过,可以检测GetAsyncKeyState的返回值最低为的值是否为1,可据此写出一个宏

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

这样就可以通过向KEY_PRESS传入键值直接监测按键是否被按过了。

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Forcible Bug Maker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值