最终的代码在最后,如果只是想要玩贪食蛇的,可以直接滑到最后直接CV。
本章我们来讲解如何用C语言实现贪吃蛇小游戏。
这篇文章很长,而且有难度,很考察你的思维能力与代码能力,希望能帮助到你,如果你无法理解,也可以找我问,我很乐意解答
话不多说,我们直接开始
目录
先看演示效果
演示效果:
以上只是模板,我们要做的是根据模板写出源代码
要想完成贪吃蛇项目,我们需要掌握C语⾔函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32API等知识,其他的不必多说,我们需要单独了解一下Win32API的知识
Win32API:
首先,我们在贪吃蛇项目中使用API是为了控制界面大小和光标位置的,这两个作用至关重要。
Windows这个多作业系统除了协调应⽤程序的执⾏、分配内存、管理资源之外,它同时也是⼀个很⼤ 的服务中⼼,调⽤这个服务中⼼的各种服务(每⼀种服务就是⼀个函数),可以帮应⽤程序达到开启 视窗、描绘图形、使⽤周边设备等⽬的,由于这些函数服务的对象是应⽤程序(Application),所以便 称之为Application Programming Interface,简称API函数。WIN32 API也就是Microsoft Windows 32位平台的应⽤程序编程接⼝。
简单来说API就是一个大的函数集合,我们要使用其中的某些函数来实现我们的目的
1.控制台程序:
控制台程序即我们平常使用的黑框程序,我们可以用CMD指令来控制控制台窗口的大小,如设置长宽,即
mode con cols=100 lines=30
即用mode指令,如有兴趣可以了解一下mode指令mode
我们不仅可以通过cmd指令控制窗口大小,还可以对控制台进行命名,即
title 贪吃蛇
效果如图所示
而这些命令,都可以在C语言中利用system函数进行调用
#include <stdio.h>
int main()
{
//设置控制台窗⼝的⻓宽:设置控制台窗⼝的⼤⼩,30⾏,100列
system("mode con cols=100 lines=30");
//设置cmd窗⼝名称
system("title 贪吃蛇");
return 0;
}
2.控制台屏幕上的坐标COORD:
COORD是WindowsAPI中定义的⼀个结构体,表⽰⼀个字符在控制台屏幕幕缓冲区上的坐标,坐标系 (0,0)的原点位于缓冲区的顶部左侧单元格。
COORD结构体包含X,Y坐标
typedef struct _COORD
{ SHORT X;
SHORT Y;
} COORD, *PCOORD;
而X,Y的相对位置如图所示
我们可以给坐标赋值
COORD pos = { 10, 15 };
3.GetStdHandle
GetStdHandle是⼀个Windows?API函数。它⽤于从⼀个特定的标准设备(标准输⼊、标准输出或标准错误)中取得⼀个句柄(⽤来标识不同设备的数值),使⽤这个句柄可以操作设备。
HANDLE GetStdHandle(DWORD nStdHandle);
HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
使用方法和使用实例如上所示,可见HANDLE是一个类型,其实就是void*类型,所以说我们创建变量初始化时,要置为NULL;
4.GetConsoleCursorInfo
检索有关指定控制台屏幕缓冲区的光标⼤⼩和可⻅性的信息
用来获得控制台的光标信息
HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息
ⅠCONSOLE_CURSOR_INFO
这个结构体,包含有关控制台光标的信息
转到定义我们可以看到两个变量
其中dwSize是光标的宽度,而bVisible是光标的可见
- dwSize,由光标填充的字符单元格的百分⽐。 此值介于1到100之间。 光标外观会变化,范围从完全填充单元格到单元底部的⽔平线条。
- bVisible,游标的可⻅性。 如果光标可⻅,则此成员为 TRUE。
而作为游戏,我们肯定不希望光标一直在频闪,这样会影响我们的游戏体验,所以我们要将bVisible设置为FALSE,即隐藏光标;
CursorInfo.bVisible = false; //隐藏控制台光标
5.SetConsoleCursorInfo
设置指定控制台屏幕缓冲区的光标的⼤⼩和可⻅性。
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);//设置控制台光标状态
从代码中我们可以看到我们要先通过函数获取控制台的地址,再修改控制台光标的信息,最后再利用函数设置控制台的状态。
6.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);
我们可以封装一个函数SetPos,从而更加方便的使用改变光标的函数
//设置光标的坐标
void SetPos(short x, short y)
{
COORD pos = { x, y };
HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//设置标准输出上光标的位置为pos
SetConsoleCursorPosition(hOutput, pos);
}
7.GetAsyncKeyState
获取按键情况,GetAsyncKeyState的函数原型如下:
SHORT GetAsyncKeyState(
int vKey
);
将键盘上每个键的虚拟键值传递给函数,函数通过返回值来分辨按键的状态。
GetAsyncKeyState 的返回值是short类型,在上⼀次调⽤ GetAsyncKeyState 函数后,如果
返回的16位的short数据中,最⾼位是1,说明按键的状态是按下,如果最⾼是0,说明按键的状态是抬起;如果最低位被置为1则说明,该按键被按过,否则为0。
如果我们要判断⼀个键是否被按过,可以检测GetAsyncKeyState返回值的最低值是否为1.
通过这个函数,在我们控制贪吃蛇进行前后左右行走时,才能及时的调整方向,也是一个重要的函数。
以上就是贪吃蛇游戏所需要用到的Win32API的知识,有点抽象,需要慢慢去理解,也可以查找资料去理解。
讲解<locale.h>
这⾥再简单的讲⼀下C语⾔的国际化特性相关的知识,过去C语⾔并不适合⾮英语国家(地区)使⽤。
C语⾔最初假定字符都是单字节的。但是这些假定并不是在世界的任何地⽅都适⽤。
C语⾔字符默认是采⽤ASCII编码的,ASCII字符集采⽤的是单字节编码,且只使⽤了单字节中的低7
位,最⾼位是没有使⽤的,可表⽰为0xxxxxxxx;可以看到,ASCII字符集共包含128个字符,在英语
国家中,128个字符是基本够⽤的,但是,在其他国家语⾔中,⽐如,在法语中,字⺟上⽅有注⾳符
号,它就⽆法⽤ ASCII 码表⽰。于是,⼀些欧洲国家就决定,利⽤字节中闲置的最⾼位编⼊新的符
号。⽐如,法语中的é的编码为130(⼆进制10000010)。这样⼀来,这些欧洲国家使⽤的编码体
系,可以表⽰最多256个符号。但是,这⾥⼜出现了新的问题。不同的国家有不同的字⺟,因此,哪
怕它们都使⽤256个符号的编码⽅式,代表的字⺟却不⼀样。⽐如,130在法语编码中代表了é,在希
伯来语编码中却代表了字⺟Gimel (?),在俄语编码中⼜会代表另⼀个符号。但是不管怎样,所有这
些编码⽅式中,0--127表⽰的符号是⼀样的,不⼀样的只是128--255的这⼀段。