历经很长时间,在下终于把贪吃蛇人工控制的版本写好,虽然略显粗糙,但也为自己初步写好一个简单游戏高兴不已。近日,又尝试了智能蛇的实现。
智能蛇与人工蛇很相似,不同之处在于一个不需要手动输入字符,另一个则需要手动控制方向。因此也就导致了两者关于移动(move)的算法不尽相同。
先来看智能蛇在判定移动方向时的伪代码:
Hx,Hy: 头的位置
Fx,Fy:食物的位置
function whereGoNext(Hx,Hy,Fx,Fy) {
用数组movable[4]={“a”,”d”,”w”,”s”} 记录可走的方向
用数组distance[4]={0,0,0,0} 记录离食物的距离
分别计算蛇头周边四个位置到食物的距离。H头的位置,F食物位置
例如:假设输入”a” 则distance[0] = |Fx – (Hx-1)| + |Fy – Hy|
如果 Hx-1,Hy 位置不是Blank,则 distance[0] = 9999
选择distance中存最小距离的下标p,注意最小距离不能是9999
返回 movable[p]
}
更细化的来看,智能蛇与人工蛇的区别也只在于判定方向的不同;即,智能蛇靠分辨距离自动判定方向,而人工蛇靠人脑分析手动输入方向。在如何移动这一点,两者算法是相同的。
因为不需要手动输入字符控制移动,总控代码也需要做相应改变:
输出字符矩阵
WHILE not 游戏结束 DO
wait(time)
ch=whereGoNext(Hx,Hy,Fx,Fy)
CASE ch DO
‘A’:左前进一步,break
‘D’:右前进一步,break
‘W’:上前进一步,break
‘S’:下前进一步,break
END CASE
输出字符矩阵
END WHILE
输出 Game Over!!!
在初期,我按照上述的伪代码写出了1.0版本,却发现一瞬间蛇就已经走过了,因此,我决定用sleep函数,以便更好地观察蛇的走向。
以下是最初版的wheregonext函数代码:
// 在全局变量中用数组movable[4]={“a”,”d”,”w”,”s”} 记录可走的方向,用数组distance[4]={0,0,0,0} 记录离食物的距离
char wheregonext(int hx, int hy, int fx, int fy) {
// Hx,Hy: 头的位置
// Fx,Fy:食物的位置
int p = 0, min = 9999;
int i;
distance[0] = abs(fx - (hx - 1)) + abs(fy - hy);
distance[1] = abs(fx - (hx + 1)) + abs(fy - hy);
distance[2] = abs(fx - hx) + abs(fy - (hy - 1));
distance[3] = abs(fx - hx) + abs(fy - (hy + 1));
// 分别计算蛇头周边四个位置到食物的距离。H头的位置,F食物位置
for (i = 0; i < 4; i++){
if (distance[i] <= min) {
min = distance[i];
p = i;
}
}// 选择distance中存最小距离的下标p,注意最小距离不能是9999
min = 9999;
return movable[p]; // 返回 movable[p]
}
这样,一个至少会吃东西的智能蛇就做出来了。可是,智能蛇的表现好像有些不尽人意。
在测试中,这只蛇总会出现回头的现象,即撞向自己的身子,这种自杀式表演显然不是我们想要的。
思前想后,我对函数作出了些许优化,当确保不会碰到身子或者边界时再移动:
将原函数改为
// 在全局变量中用数组movable[4]={“a”,”d”,”w”,”s”} 记录可走的方向,用数组distance[4]={0,0,0,0} 记录离食物的距离
char wheregonext(int hx, int hy, int fx, int fy) {
// Hx,Hy: 头的位置
// Fx,Fy:食物的位置
int p = 0, min = 9999;
distance[0] = abs(fx - (hx - 1)) + abs(fy - hy);
distance[1] = abs(fx - (hx + 1)) + abs(fy - hy);
distance[2] = abs(fx - hx) + abs(fy - (hy - 1));
distance[3] = abs(fx - hx) + abs(fy - (hy + 1));
// 分别计算蛇头周边四个位置到食物的距离。H头的位置,F食物位置
if (distance[0] <= min && (map[hy][hx - 1] == ' ' || map[hy][hx - 1] == '$')) {