【问题标题】:Pathfinding for 2D tile map for multiple goals用于多个目标的 2D 瓦片地图的寻路
【发布时间】:2015-03-03 19:17:32
【问题描述】:

我正在尝试用 C++ 创建一个简单的基于网格的游戏。寻路是其中必要的一部分。我一直在寻找,但没有我想要的东西。

规则很简单。有一张地图。大小通常不超过 100 x 100 瓷砖。 1是地砖,0是墙。不允许对角线移动,因此每个网格只有 4 个方向。然而,目标大多不止一个。我想找到最近的路。请记住,我们不能只计算,哪个是最近的距离公式。由于墙壁,距离较短的目标可以走得更远。我认为使用一种已知算法并针对每个目标重复并不是一个好主意,因为它会变慢。

你有什么看法?我该怎么办?

【问题讨论】:

  • A* 在 4 连接空间中的 100 x 100 网格上将非常快(记得使用曼哈顿距离!)。您最好的选择实际上是简单地在所有这些上运行它并比较最终路径长度,因为如果不知道到达该目标的最佳路径,就无法根据您的定义确定哪个目标“最接近”。如果您的地图是静态的,您可以通过将其重新编码为图来进一步提高效率,其中顶点是连接的单元格(想想走廊),节点是路径中的分支,因此您需要遍历的状态更少。
  • 如果你多次使用同一张地图进行寻路,我会考虑预先计算每个字段到其他字段的距离(当然不包括墙壁)
  • @tobi303:这是非常昂贵的 O(N*N) 并且通常不需要。取100x100的地图;你需要 O(100x100x100x100) 距离。对于可能合理的图表(并且这个网格将是),拥有数量少得多的常见“快捷方式”就足够了。例如。如果您可以识别死胡同,您只需要从死胡同中的每个点到颈部点的距离。
  • @MSalters 如果您使用同一张地图并进行许多寻路,那么如果您预先计算所有距离,则单次寻路的成本实际上是 O(1)。您只需在列表中查找即可。这种预先计算可以在“运行前”完成,所以我不明白你为什么称它为“非常昂贵”。特别是,您提到的技巧也可以在预先计算距离时应用。
  • @MSalters 另外,我猜,非墙砖的数量远低于 100x100。如果它只是 100x100,就不需要复杂的算法。当然,如果游戏每次使用不同的地图,预先计算就没有意义,但它确实会“非常昂贵”。

标签: c++ path-finding


【解决方案1】:

这不是什么大问题。添加到所有真实目标距离为 1 的假设结束节点 E,并搜索到 E 的最佳路径。路径上的最后一个节点将是这些真实目标之一。

【讨论】:

  • 这将有助于说明这将如何与像 A* 这样的算法的 huristic 部分一起工作(或者如果它不会)。您如何计算到虚拟位置的 huristic 距离,从而以有意义的方式引导搜索?
  • @aruisdante:与真实路径相同:H(E) = 1 + min(H(goals))
  • 按照定义,这难道不是总是将搜索偏向于物理上最接近的目标,而不是最短路径长度的目标吗?它显然会起作用,但我想知道它是否真的会比单独对每个目标进行 A* 更快。我想这将很大程度上取决于地图配置。但可能在大多数情况下会更快。
  • 啊等等,我以为它会是静态计算的。当然,如果您在每个状态下重新计算 min(H(goals)),它总是会让您在搜索中偏向与该状态最接近的目标,这几乎可以肯定是正确的做法。
  • @你只需要为你在 A* 搜索中遇到的节点计算它(懒惰地),但是一旦你计算了它,你就可以重复使用它,直到目标改变。
【解决方案2】:

正如其他人所说。考虑对图形进行编码,也许最好的方法是为所有图块预先计算。我基本上会选择 Floyd-Warshall 算法。 https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm

【讨论】:

    【解决方案3】:

    可能有助于解决此问题的小技巧:使用 A* 从所有目标同时搜索到起点,然后反转路径。这比在每一步中计算到每个目标的最小曼哈顿距离或向图中添加额外节点要简单。

    由于 A* 通过 OPEN 列表维护成本最低路径的候选者列表,因此您可以简单地将所有目标图块插入到该打开列表中。由于打开列表是一个优先队列,A* 将通过首先尝试启发式关闭目标,然后仅在明确到达目标的路径为时才切换到更远的目标,从而从任何目标中找到成本最低的路径成本更低。这为您提供了从最佳目标到起始位置的路径,然后您只需将其反转即可获得从起始位置到目标的路径。

    【讨论】:

      【解决方案4】:

      A* 是一种可用于在 2D 网格上进行寻路的算法。 Here's a good simple A* tutorial.

      虽然您可以多次运行该算法,但对于每个目标,另一种方法是使用“Dijkstra 算法”算法,该算法与 A* 不同的是在各个方向上均匀扩展,直到找到所有目标并选择具有最好的结果。

      【讨论】:

      • 一个小挑剔,Dijkstra 的平均扩展基于路径成本,而不是节点数。当然,如果所有节点的遍历成本相同,则它们是等效的。 A* 只是 Dijkstra 的,通过有效地将节点到目标的距离添加到遍历它的成本(使遍历节点的成本使您朝着目标“更便宜” )。如果您在 A* 中将启发式成本权重设置为 0,您将得到 Dijkstra。如果您在 A* 中将路径成本权重设置为 0,您实际上会得到深度优先搜索。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-06
      • 1970-01-01
      • 2012-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-23
      相关资源
      最近更新 更多