标签:start 双向 处理模块 信息 第一个 循环 处理 sig std
本文首发于我的个人博客www.colourso.top,欢迎来访。
原文链接:http://www.colourso.top/c-snake-pro0/
原文写于2019-06-21,本次重新整理。
EasyX 是针对 C++ 的图形库,可以帮助 C 语言初学者快速上手图形和游戏编程。
官网链接:https://easyx.cn/
先开始写文档,分析要实现哪些功能,然后对功能进行细分,梳理操作。以下80%的内容都是当时写贪吃蛇的文档,后期整理一下发博客记录。
贪吃蛇游戏的简单版本实现
实际上游戏的坐标都是采用原点在左上角,这里因为我设置了坐标轴的原因导致了后面文字摆放无法放置正确,也是因为这个原因,要重写了第二版代码。
对于食物而言,一次只会出现一个食物,只需要保存它的坐标位置,以及存在状态即可。
struct Food //食物结构体
{
int x; //横坐标
int y; //纵坐标
bool exist; //是否存在,1表示存在
};
对于蛇而言,蛇是由一个个节点构成的,每吃一个食物就会增加一个节点。并且所有节点都连接起来,采用链表是一个不错的选择。
结构体设置模仿自严蔚敏老师的数据结构链表的设置。定义蛇节点结构体,然后定义蛇的结构体。
本来采用的单向链表,但后续处理蛇的移动算法时发现需要从后向前复制节点的操作,于是改成了双向链表。
这里也可以采用数组啦、STL的vector容器啦来处理蛇的结构体。采用链表复习复习数据结构。
typedef struct Node //蛇的节点
{
int x; //横坐标
int y; //纵坐标
struct Node * next; //指向下一个节点的指针
struct Node * pre; //指向前一个节点的指针
}* LinkNode;
struct Snake //蛇的结构体
{
LinkNode head; //指向头节点的指针
LinkNode tail; //指向尾节点的指针
int direction; //蛇头方向
int num; //节点数目
};
贪吃蛇的移动完全是复制头部节点,蛇头控制方向与前进,其他节点均是重复前一个节点的行为。
而在处理蛇移动的时候,先要用后面节点的保存了它的前一个节点的坐标信息。故蛇身移动的算法,是从最后一个节点(tail)向前复制前一个节点的坐标,达成移动效果。
想到这里就把蛇的结构体改为双向链表。便于我的操作。
LinkNode linknode = snake.tail;
while (linknode != snake.head)
{
linknode->x = linknode->pre->x;
linknode->y = linknode->pre->y;
linknode = linknode->pre;
}
食物生成要具有随机性,并且要求食物不能够生成在蛇的身体上。
随机数函数rand()产生随机数,rand()函数需要的头文件是:<stdlib.h>。
rand()会返回一个范围在0到RAND_MAX(32767)之间的伪随机数(整数)。
在调用rand()函数之前,可以使用srand()函数设置随机数种子,如果没有设置随机数种子,rand()函数在调用时,自动设计随机数种子为1。随机种子相同,每次产生的随机数也会相同。
srand( usigned int seed)函数用来设置rand()产生随机数时的随机数种子。参数seed是整数,通常可以利用time(0)的返回值作为seed。srand()函数需要的头文件是:<stdlib.h>
例如:生成0-6之间的任意一个随机数
srand(time(0));
int num = (rand()%7)//模求余
食物不能够在蛇的身体上,即生成坐标之后遍历蛇的节点进行匹配,若有对应的就直接重新生成一次。
int x;
int y;
while (1)
{
srand(time(0));
x = (rand() % 24) * 20 + 10;
y = (rand() % 24) * 20 + 10;
//食物位置检测算法
LinkNode linknode = snake.head;
bool cont = true;
while (linknode != snake.tail->next)//从头遍历到尾巴
{
if (linknode->x == x && linknode->y == y)
{
cont = false;
break;
}
linknode = linknode->next;
}
if (cont)
{
break; //如果食物不在蛇的身体上,就break退出循环
}
}
food.x = x;
food.y = y;
food.exist = true;
_khbit()
函数用来检测是否有键盘输入。如果有按键被按下,会返回一个1,否则返回值为0.它是一个非阻塞函数,无论有没有按键被按下,他都会立即返回结果。可以用来做循环的条件判断是否有按键,或者等待输入。
_getch()
函数作用是从控制台获取输入的字符,并返回获取到的字符值。而且这个函数是阻塞性函数,必须要获取输入字符后才会返回。
_kbhit()
与_getch()
都是位于conio.h
头文件中。(console IO)
int keys = 0;
int key;
while (1)
{
if (keys = _kbhit())
{
key = _getch();
cout << "按键的值key:" << key << endl;
}
}
由此可以测的我们按键对应的键值是多少。
方向键↑ 对应值为72。
方向键↓ 对应值为80。
方向键← 对应值为75。
方向键→ 对应值为77。
但是相信执行这一段代码会发现按一次键会有两个key被打印出来。但是写switch语句(代码中的按键处理模块)时却完全和第一个key值无关。这个问题暂时还没有解决!路过的大佬欢迎留言~
这个方法我是从某潭某州的公开广告课上学到的。
其他参考链接:C++中_kbhit()函数与_getch()函数
int main()
{
初始化资源;
绘制界面;
开始游戏:
while(1)
{
if(!食物存在)
{
刷新食物并显示
}
if(按键)
{
相应操作:蛇头方向:上下左右
}
向蛇头方向前进1格。绘制蛇头
(switch case结构)
消除蛇尾图像。
judge(蛇头吃食物)
{
蛇结点+1,尾巴加长并显示出来
分数增加
食物状态刷新
}
judge(撞墙or撞自己)
{
死亡
game over
break
}
sleep(200)
}
结束 回收资源;
}
标签:start 双向 处理模块 信息 第一个 循环 处理 sig std
原文地址:https://www.cnblogs.com/colourso/p/12983840.html