我有一个问题,我需要实施一个算法来查找从一个字符到另一个带有障碍物的字符的路径。
我知道有很多高级寻路算法(A *,BFS,DFS,dijkstra ....)。但是,经过大量的研究和尝试,我一直在努力在代码中实现所有这些概念,并且我也不认为我需要实现所有这些高级算法。
“最短”路径不是必需条件,而我所需要的只是一条路径,它可以避免移动到障碍物上,从而将我的角色引导到另一个角色。 谁能给我一个解决这个问题的想法(也许比回溯更好的算法)或有用的网站(类似的例子)?
任何帮助将不胜感激
答案 0 :(得分:0)
我可以向您推荐A *算法。
它易于实现算法。对于我的A *,我使用了wikipedia代码和geekforgeek代码。
我还将在C#中发布其代码,但与Java非常相似:
batch size = 1
此代码的重要之处在于,在搜索之前必须定义邻接节点,可步行节点以及不步行节点。
希望我的代码可以帮助您在代码中实现A *。
答案 1 :(得分:0)
由于我不知道如何描述“网格”以及“单元格”的含义,因此我假定网格是矩形的,因此单元格仅将对象映射在其上,而不是空白。
我建议您使用某个值对char[][] array = new char[rows][columns];
(或char)进行初始化,然后在Cells
上进行迭代,以某种有意义的方式填充2D数组,例如,目标为G
,#
表示障碍,等等。然后从目标启动DFS以查找开始。
您需要将正确的路径存储在某处,因此也需要一个ArrayList list;
变量。由于是列表,因此可以使用方便的list.add(item);
向其中添加项目。
DFS是一个非常基本的递归算法,在您的情况下,它将像这样:
bool DFS(list, array, row, column):
if(array[row][column] == '#' or
array[row][column] == 'v') return False; # Obstacle or visited, ignore it
if( ... == 'S') return True; # It's the Start, path found
array[row][column] = 'v'; # mark as visited, nothing interesting.
# If you want the shortest path, you're supposed to put here the distance from goal,
#that you would pass on and increment as additional argument of DFS
#Check for edge cases, or initialize array to be bigger and place obstacles on edge#
if( DFS(list, array, row-1, column) ){ # If DFS fount a path to Start from cell above
list.add("Move Up"); # Then you add a direction to go below to the list
return True; # And then tell the previous DFS, that the path was found
}
if()
if()
if()
# And then you add the checks for the other directions in a similar manner
return False; # You didn't find anything anywhere
}
那不是代码,但是从那里开始您的分配应该足够了。
有机会找到这样的路径:
...→→→→↓
...↑.↓←↓
...S.F↑↓
......↑↓
......↑←
但是在有很多障碍或只有一条正确路径的网格中,它将形成更合理的路径。另外,您还可以通过选择尝试的顺序来改进它,以便始终始终尝试先达到目标,但这很痛苦。
要找到通常人们引用A *的最短路径,但我仔细阅读了一下,它并不是我所记得的,它不必要地复杂,因此我将解释扩展的DFS。找到答案所需的时间比A *或BFS更长,但是对于合理大小的网格而言,它并不明显。
该算法的思想是将整个网格映射到Goal
的距离,然后随着距离的减小而从起点到目标。
首先,您需要使用int[][] array
而不是前一种情况的char
。这是因为您需要存储距离(char在某种程度上也可以存储),还需要存储栅格中的非距离标记(例如障碍物等)。
算法的思想是调用DFS(array, row, col, distance)
,其中distance
的计算方式是调用DFS的Cell
的距离增加了1。然后下一个单元格中的DFS检查是否它经过的距离小于当前距离,如果是这样,则发现该单元格的路径较短,您也需要重新计算其所有邻居。否则,新路径会更长,您可以忽略它。通过递归调用DFS,您将逐渐映射整个迷宫。
此后,您将调用另一个函数FindPath(list, array, row, col)
,这将检查它开始的单元格,并向neighbor.distance == (this.distance - 1)
添加list
到该单元格的方向,然后调用{{1 }},直到距离为0,这才是目标。
它看起来应该像这样:
FindPath
它并不复杂,但是它为您提供了最短的路径。这不是找到最短路径的最快方法,但是相对于任何递归算法而言,它都相对简单。