关于贪吃蛇的碰撞算法:
- 需求分析:我们需要判断贪吃蛇在移动的过程中是否碰到墙或者自己的身体:如果碰到了,则游戏结束,在屏幕上输出相应的有关游戏结束的界面;如果没有碰到,则游戏继续。
- 算法实现:无论蛇本身的数据结构是结构体数组还是链表,我们只需要判断蛇头有没有撞墙或者撞到自己的身体就可以了,因为只要蛇头没有撞墙,那蛇身是一定不会撞墙的。
所以我们首先需要获取蛇头的位置信息:
如果蛇的结构是结构体数组,我们可以用结构体数组中蛇头对应的下标获取蛇头的位置信息;
如果蛇的结构是链表,我们可以用头节点获得蛇头的位置信息;
在获得了蛇头的位置信息之后,我们只需要判断蛇头是否撞墙就行了。
那么,如何判断蛇头是否撞墙呢?
通过查询资料:我们主要介绍以下两种常用的方法:
算法1:
(1)可以事先在全局定义一个用于存储地图中各位置状态的数组,数组的大小至少为整个地图的最大长度×最大宽度,这样才能保证这个数组能够储存地图中所有位置的状态。(这里的状态包括:“空”,“墙”,“蛇头”,“蛇身”,“食物”)
具体方法如下:
①先构造大小至少为地图最大长度×最大宽度的整型数组:
即 int face [ ROW ] [ COL ]; (其中ROW是地图的宽度,COL是地图的长度)
②接着进行初始化(初始化的方法很多,这里仅给出例子)
for ( int i = 0 , i < ROW ; i++ ) /*事先宏定义HEAD, BODY, WALL, FOOD, KONG
{ 对应各不同的数值*/
for ( int j = 0 ; j < COL ; j++ )
{
if ( i == 0 || i == ROW - 1 )
{
face [ i ] [ j ] = WALL; //标记墙的位置
}
else if ( j == 0 || j == COL - 1 )
{
face [ i ] [ j ] = WALL; //标记墙的位置
}
else
{
face [ i ] [ j ] = KONG; //标记空的位置
}
}
}
需要注意的是,在蛇每次移动的过程中,需要实时更新地图中的位置信息,即把蛇头下一个将经过的位置标记为蛇头,然后把蛇身所在的位置全部标记为蛇身,最后把蛇尾将离开的位置标记为空。在生成食物的时候,把食物生成的位置标记为食物。具体的实现方法就是:在写关于蛇的运动的那一块函数时顺便更新一下地图位置信息就行了。
(2)然后,在蛇每次移动的过程中,所记录的蛇头下一次即将到达的位置,与当前存储的地图位置信息比较:如果下一次即将到达的位置是墙或者自己的身体:
即 ( face[head.x + x][head.y + y] == WALL || face[head.x + x][head.y + y] == BODY )
其中head.x和head.y是当前蛇头的位置,x,y是蛇头将要移动的位移,则如果上条件成立,说明蛇头即将到达的位置是墙或者自己的身体,这时我们就可以判定游戏结束,进行下一步的工作了。
(3)算法分析:该算法的核心思想与哈希算法类似,地图位置信息的构造与初始化是简单的,难点在于如何实时更新地图中的位置信息。算法1主要基于地图对蛇头的碰撞进行分析。
算法2:
(1)直接利用蛇头的位置坐标,根据蛇头的位置坐标直接判断是否与墙或者自己的身体碰撞。该方法用于判断蛇头是否与墙碰撞是容易的,但是用于判断蛇头是否与蛇身进行碰撞则需要遍历蛇身的位置坐标(需要花点心思):
具体方法如下:
①首先需要获取蛇头的位置坐标,方法上面已经介绍了,
这里假设head.x和head.y是当前蛇头的位置,ROW是地图的宽度,COL是地图的长度。
②判断是否与墙相碰:
if ( head.x + x == 0 || head.x + x == COL - 1 || head.y + y == 0 || head.y + y == ROW - 1 )
③判断是否与蛇身相碰:
判断是否与蛇身相碰,显然我们需要遍历蛇身的每个节点的位置坐标,将其与蛇头当前的位置坐标进行比较,如果相等,则说明蛇头即将与蛇身碰撞;
遍历蛇身的每个节点方法有很多,下面给出一个例子:
显然对于链表的数据结构来说,遍历是极其简单的:
· SNAKE head_copy = head -> next ; /* 假定蛇的结构体变量名称是 SNAKE
· while ( head_copy -> next != NULL ) 然后声明一个另外的变量指向第一个
{ 蛇身节点,再进行遍历 */
If ( head_copy . x == head . x && head_copy . y == head . y )
{
******* /* 如果蛇头的坐标与某一个蛇身的节点重合
******* 则蛇头与蛇身相碰,执行相应的操作 */
}
}
(2)算法分析:该方法的思路较为直接,简单粗暴,但难点在于对蛇身每一个节点的遍历。算法2主要基于蛇头的坐标对蛇头的碰撞进行分析。如果是链表的数据结构的话,推荐使用算法2。