超级贪吃蛇(贪吃蛇,怎么不死)
应用介绍
在玩贪吃蛇游戏的时候一个基本问题是如何能够让蛇不死。如果一个方法能够让贪吃蛇一直不死且能走到地图上的任意位置,那么我们也就能够得到一条最长的贪吃蛇。如:
贪吃蛇模型
在贪吃蛇游戏中,蛇每吃到一个苹果,身体会变长。当蛇撞到障碍物或者自己的身体时,则游戏结束。我们讨论两种平时玩的最多的贪吃蛇地图模型,无墙地图和有墙地图。顾名思义,无墙模型中贪吃蛇走到地图最边上时能够从地图的另一侧出来。
而有墙地图中,撞墙则死。
在两种模型中,找到不死贪吃蛇的关键是能找到一条遍历图上所有格子的环路,则沿着此环路行走,既能吃到所有的苹果又不会和身体相撞。
无墙地图中的不死贪吃蛇
在无墙的地图中,根据地图的行数为奇数还是偶数会有不同的走法。
最简单的是行数(或者列数)为偶数的情况。假设行数为偶数,我们可以通过横向扫描的方法找到一个遍历所有点的环路。如图
当行数和列数都为奇数时,上面的方法不适用了,但我们在第一第二行执行W型的行走,在其余行执行横向的扫描可以找到一条遍历所有点的环路。如图
有墙地图中的不死贪吃蛇
有墙地图中周围的一圈墙使得上述的两种方法不能直接适用。于是我们需要在围墙之内找到一条蛇的“回路”。
当行数为偶数时,将第一列作为“回路”,我们可以得到一条遍历所有格点的环路。如图
当行数和列数都为奇数时,似乎找不到一个遍历所有格点的环路(未证明),但如果我们删去一个点,如最左上角的点,则可以得到一个遍历其他格点的环路。为了解决苹果出现在最左上角的情况,我们找到2条路径,它们唯一的差别是否经过左上角的点。这两条路径能够自由的切换。如图。只有当左上角的苹果为最后一个格点时,蛇才会在吃完此苹果后走入绝境。此时游戏判断格子占满,结束了。
快速贪吃蛇算法
不死贪吃蛇算法虽然最终能够走遍所有格子,但时间复杂度非常高。假设地图是n*n的,那么最坏情况下每吃一个果子,就要行走n^2个点。因为共有n^2个果子,所以完成游戏需要经历n^4个格子。又在贪吃蛇游戏中蛇的行动是匀速的,所以时间复杂度是O(n^4).
我们发现在不死贪吃蛇中,当蛇的长度比较短时,很多路径是没有必要走的。蛇行走很长路径是为了“消化”自己太长的身体。如果我们能够根据蛇的身体长度和果子出现的位置,找到一些较短的回路,那么蛇吃到一个果子的时间就会缩短。一个自然的想法是每次寻找一个能吃到果子的最短的环路。我们提出一个基于最小环路的快速贪吃蛇算法(ShortestRing-Based Fast Snake).
最小环路快速贪吃蛇算法
我们发现,通过添加回路,我们能够从大的贪吃蛇环路上构造出若干个小的环路。蛇沿着这些小的环路又能够自由的进入大的环路而不碰撞到自己的身体。这些小的环路要经过果子,且长度至少是蛇的身长+1(吃了果子会变长)。并且小环和大环相交的地方走向要一致。如图。
图中灰色通道是我们添加的回路。我们发现,通过添加回路,我们能够得到一些较小的环。绕着这些环行走,蛇能够以较小的行动路径吃到一个果子。同时蛇又能够自然的从小环路走到大环路中(图上绿色虚线部分)。构造小环路的方式不是唯一的,好的构造方法能够让我们尽快的吃到果子。
考虑蛇吃完一个果子要走到下一个环路,可以找一条两个环路间最短的路线。这条路线最长为行的个数n。
所以吃到一个果子的时间减少为(蛇身长+1+n)。通过求和,其时间复杂度虽然仍为O(n^4)但系数有所减少。
下一篇:黄龙峡漂流(汉城湖公园要门票吗)