C语言--贪吃蛇项目(1)

发布于:2024-04-19 ⋅ 阅读:(33) ⋅ 点赞:(0)

1.设置和win32API函数介绍

(1)终端应用程序设置

我们要在终端完成这个游戏的实现,那么就要设置控制台的窗口,只有在下面的命令下,游戏才能正常的执行(请读者自行检查):

在弹出的窗口里面调整设置:

查看对应的设置,看看是否需要进行修改:打开设置之后,查看这个地方是否为“控制台主机”,如果已经是的话就不需要进行相应的修改,否则接调整为这个命令;

(2)终端名字和行列数的设置

我们想要控制这个终端的行数和列数,把这个终端的名字改为我们的游戏的名字:贪吃蛇;我们就需要调用system这个系统的函数进行相应的控制;这个系统函数的调用需要包含对应的头文件stdlib.h才可以进行使用;

mode con cols lines是设置相应的终端的页面的大小(包括行数和列数);

title是设置终端的对应的名字,如果你直接像上面的一样写上去,肯定无法修改我们的终端的名字的,因为我们一旦运行,这个程序就结束了,我们的程序就直接结束了,我们要想看到对应的名字设置,可以使用getchar()命令,或者是定义一个变量,使用scanf输入对应的值,这样的话就可以把程序停下来,我们就可以看到对应的名字的设置了。当然,我们也可以使用system("pause");这样就可以暂停程序,我们需要按下回车键程序才会完全的结束。

(3)坐标轴的设置

我们想要控制食物的放置,以及这个贪吃蛇的运动的轨迹和方向,我们就需要设置对应的坐标,我们的控制台里面的坐标的设置和我们的数学里面的坐标轴稍有区别,对于我们的终端窗口,左上角的位置为(0,0)位置,从这个点开始,向右就是x的正方向,向下就是y轴的正方向,我们想要设置对应的坐标,就需要调用对应的系统类型OCCUR,这个就是一个结构体类型,我们可以直接进行使用,但是需要包含对应的头文件(头文件里面含有对这个结构体的定义和声明),我们使用下面的方式对我们定义的结构体类型的变量设置对应的坐标:

(4)句柄设置

我们的HANDLE是一个指针的类型,我们可以先把我们定义的Houtput设置为NULL,然后再对其赋值;API是一个类型的函数,里面的函数就是针对我们的终端进行设置的,我们这里只是使用了API里面的一个函数进行了句柄的设置

(5)光标是否闪烁的设置

我们运行程序的的时候,发现有个光标不停的闪烁,等待我们输入对应的数据,我们可以不让这个光标闪烁,进而在贪吃蛇运行的时候,让我们的页面更加的整洁;

houtput就是我们上面提到的句柄,GetConsoleCursorInfo就是一个函数,我们可以直接进行使用,这个函数有两个参数,我们需要传进去的第一个参数就是我们的句柄信息,第二个参数就是我们自己定义的一个结构体变量的地址,这个结构体变量用来存放我们的光标的相关的信息;

设置成false就不会显示光标,默认的显示光标应该是true,相当于是我们手动进行了修改;

(6)设置光标位置

这个时候,我们就可以把光标打印到我们自己设置的(30,30)这个坐标的位置;

我们也可以把这个功能封装成一个函数,这样我们可以直接进行调用:

(7)检测按键

GetAsyncKeyState 的返回值是short类型,在上⼀次调⽤ GetAsyncKeyState 函数后,如果
返回的16位的short数据中,最⾼位是1,说明按键的状态是按下,如果最⾼是0,说明按键的状态是抬起;如果最低位被置为1则说明,该按键被按过,否则为0。
我们这里使用的是不同的按键的"虚拟键代码"(这个同学们可以下去自行了解),就是每个按键都对应着一个虚拟键代码,我们使用这个对应的虚拟键代码和1进行按位与操作,如果结果是1,说明我们按过了,否则就没有按过,我们可以使用一个宏进行相关的定义;
#define KEY_PRESS(VK) ( (GetAsyncKeyState(VK) & 0x1) ? 1 : 0 )

这个里面的VK就是虚拟键代码,我们使用外面的函数GetAsyncKeyState进行判断这个键是否被按下,我们这里使用的是三目运算符,这个里面的KEY_PRESS就是一个我们自己定义的函数,我们需要使用这个函数进行相应的判断,我们可以在主函数里面直接调用这个函数,例如我们可以利用

if (KEY_PRESS(0x30))
 {
 printf("0\n");
 }

这样的话,如果我们按键了0,就会打印数字0,这里的0x30就是0这个键的虚拟键代码;

2.本地模式的设置

我们在地图里面使用方块代表的是蛇身上的节点,我们使用星号代表的是食物,这些都需要宽字符进行表示,我们之前的使用百分号c以及百分号s打印的内容都是普通的字符,我们的宽字符就是宽度要比普通的字符要宽一些,我们之前是使用char关键字定义变量,现在我们要使用wchar_t来进行定义变量,我们想要定义的变量的前面要加上L,我们打印字符的时候要 使用的是wprintf进行打印,打印使用的是%lc,而且在这个符号的前面要加上L;
最上面的setlocale是把我们的程序设置为本地的,这个就会支持把我们的汉字作为宽字符进行输出,这个的使用需要添加上对应的头文件。

3.游戏实现

(1)我们要创建一个头文件和两个源文件用来管理我们的项目;头文件负责相关的函数的声明,蛇的节点的结构体的定义,蛇的运动方向的枚举类型的定义,蛇本身的结构体的定义;

(2)因为蛇的头部,蛇的移动的方向,以及蛇的运动的状态,蛇吃的食物,运动的过程中得到的分数,都是蛇本身这个结构体应该包括的全部内容;

(3)蛇的节点这个结构体,我们应该进行节点处的坐标的定义,以及指向下一个节点的指针,这个里面就是通过链表的方式进行的相关的节点的有序的连接;
(4)蛇的运动状态我们同样是使用的枚举的方式进行定义的;我们没枚举了几种贪吃蛇可能会出现的运动的状态;
(5)在test.c文件里面,我们进行的是贪吃蛇的创建,创建了一个结构体类型的变量,我们通过gamestart这个函数开始我们的游戏,我们要向修改这个贪吃蛇的某些信息,就要把我们自己定义的贪吃蛇的地址传递过去;
我们在测试的文件里面同样进行了本地环境的配置,调用yesy函数,test函数里面就是我们贪吃蛇游戏的基本框架;
(6)这个gamestart函数的设计,我们首先要隐藏相应的光标,设置终端的名字,以及终端的窗口的大小,接着就可以进入我们的欢迎界面,欢迎界面代码我们有重新封装了一个函数;
首页的页面的效果就是下面这样的:
前面的两张图片就是对应的页面的提示,最后的一张就是我们的贪吃蛇运行的地图的设计;接下来我们依次进行实现:
(6)首先就是页面欢迎的设计,我们要输出一些提示语:比如欢迎来到贪吃蛇小游戏,然后读者按键之后才可以进入下一个页面,下一个页面的出现要求我们清除现在的界面,并输出使用那些按键控制贪吃蛇的移动,加速和减速的按键设置,这个过程中,为了页面的整洁,我们需要用到setpos函数设计对应的位置,这个函数的实现我们首先要得到相应的句柄然后再定位光标的位置
(7)地图的创建:这个就要严格的按照相应的坐标进行设计,横着的应该是宽字符,数量应该是竖着的2倍,我们需要利用循环打印这些点作为地图里面的墙体,分为上下左右4个方向;
(8)对贪吃蛇进行初始化操作,这个过程我们要确定这个里面每个节点处的坐标,这个就是用链表把相邻的节点串联起来,我们要找到不同的节点之间的相同点和不同点,相同点就是他们的横坐标都是一样的,不同点就是他们的纵坐标是一个公差为2的等差数列,我们先设置初始的时候这个贪吃蛇的节点是5个,接着我们使用next指针,把这几个节点串联起来,我们新定义一个指针cur,首先要判断原来的链表是否是空链表,如果是空的链表,我们就直接把cur赋值给我们的贪吃蛇的psnake成员变量,如果不是空的我们就进行遍历,也就是链表里面的头插的方法,最后我们一个一个的判断cur是否为空,不是空的话我们就把对应的坐标传递给我们的setpos函数使他显示在我们的地图上面;
接下来的几行代码是对贪吃蛇的其他的属性进行初始化,例如刚开始的时候这个弹贪吃蛇的运动的方向,我们这里默认的方向是向右的(这个方向就在我们前面定义的枚举类型里面,有4种选择),我们定义了贪吃蛇的移动速度是200,初始情况下的得分是0,刚开始的转台设置为ok即可