Android 路径查找算法

背景

我正在开发一个简单的2D游戏,其中一些“僵尸”会追赶我。

我计算路径的想法如下(X = 路径不可用):

[4] [4] [X] [1] [1] [2] [3] [4] [5][3] [X] [X] [0] [1] [X] [X] [X] [5][3] [2] [1] [1] [1] [X] [3] [4] [5][3] [2] [2] [2] [2] [2] [3] [4] [5]

从0开始,给它周围的位置赋值1,靠近1的位置赋值2,以此类推。这样我只需要搜索较低的索引,就可以知道到达0的最快路径。

问题

(1) 我不知道这种算法是否有名称,因此我找不到相关的资料。

(2) 计算此路径的最佳解决方案/算法/流程是什么?

(3) 在我的手机上,游戏屏幕的分辨率为1700 x 1440,所以我的代码需要15秒。我创建了一个最终值来缩小所有内容并降低矩阵大小,但仍然需要很长时间,实际上无法玩。

(4) 是否有其他需求?也许需要添加线程?我不知道这样做是否有效…

我的代码 (调试代码已删除)

代码

private void expandAllFrom(int x, int y){ // x和y已经缩小    nodes = new ArrayList<Point>(); // "nodes"是一个全局变量 //    nodes.add(new Point(x, y));    while ( nodes.size() > 0 ){        Point p = nodes.remove(0);        expand(p.x, p.y);    }}private void expand(int x, int y){    int limXMin = x - 1, limXMax = x + 1, limYMin = y - 1, limYMax = y + 1;    int value = map[x][y];    // 检查屏幕边界    if ( limXMin < 0 ) limXMin = 0;    if ( limXMax > SCREEN_X_DIV - 1) limXMax = SCREEN_X_DIV - 1;    if ( limYMin < 0 ) limYMin = 0;    if ( limYMax > SCREEN_Y_DIV - 1) limYMax = SCREEN_Y_DIV - 1;    for (int i = limXMin; i <= limXMax; i++){        for (int j = limYMin; j <= limYMax; j++){            if ( map[i][j] == 0 ) {                if ( i != x || j != y ){                    nodes.add(new Point(i, j));                    map[i][j] = value + 1;                }            }        }    }}

解释

我使用了一个先进先出(FIFO)列表。我将节点添加到其中,例如,流程会是这样的:

(1) 将0位置添加到扩展节点列表中。(2) 通过在其周围设置1值来扩展0。然后将它们添加到扩展节点列表中。(2) 通过在其周围设置2值来扩展1。然后将它们添加到扩展节点列表中。(...)(X) 通过在其周围设置3值来扩展2。然后将它们添加到扩展节点列表中。(Y) 通过在其周围设置4值来扩展3。然后将它们添加到扩展节点列表中。(...)

回答:

如前所述,你所做的是广度优先搜索,这是Dijkstra算法的一个特例。祝贺你自己发现了这一点!

问题在于,BFS的时间复杂度是O(V+E),其中V是节点数,E是边的数量。在你的情况下,它将取决于地图的大小和地图的稀疏度(即有多少X)。无论如何,对于1700×1440大小的地图,这将是数百万的数量级。

如果僵尸的数量不是太多,逐个计算每个僵尸的最短路径会快得多(你仍然可以在僵尸之间共享和重用扩展的节点),使用带有启发式的BFS变体。例如,跳点搜索针对统一成本迷宫进行了优化(跳点搜索是A星算法的一个特例)。

这里的想法是从一个起点(僵尸的位置)和一个终点(玩家的位置)开始,计算它们之间的最短路径,首先扩展离目的地更近的节点。这里的“更近”是指到终点的近似距离较小。到达的节点的距离是已知的,A星将选择从起点到节点的距离加上从节点到终点的近似距离之和最小的节点。由于你允许对角移动,距离近似不能是曼哈顿距离,也不是欧几里得距离,因为近似必须是真实距离的下限。你可以使用例如max(│x-x’│, │y-y’│)。跳点搜索通过利用地图的迷宫结构,进一步排除更多的节点来改进这一点。

这个网站动画展示了几个这样的算法,你可以感受一下这些算法是如何工作的。

这种方法的好处是你不会搜索整个地图,只搜索僵尸和玩家之间的很小一部分。这可能比任何全尺寸的BFS算法快几个数量级。为了展示加速效果有多显著,请看以下图片。只有标记的节点被搜索探索:

A星搜索跳点搜索

另一个优点是,你可以在运行时间和僵尸的“聪明程度”之间进行权衡。你所要做的就是不要将这种算法一直运行到终点。你可以在预定义的步骤数后停止,并获得路径开始部分的近似值(通过查看起点和下一个最有希望扩展的节点之间的最短路径)。所以根据你有多少时间进行计算,你可以拥有最优或不太优的僵尸。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注