bbe*_*ard 2 java algorithm recursion maze
我做了一个小递归算法,以下列格式找到迷宫的解决方案
###S###
##___##
##_#_##
#__#_##
#E___##
Run Code Online (Sandbox Code Playgroud)
其中'#'代表墙,'_'代表开放空间(可自由移动).'S'代表起始位置,'E'代表结束位置.
我的算法工作正常,但我想知道如何修改它以适应最短的路径.
/**
* findPath()
*
* @param location - Point to search
* @return true when maze solution is found, false otherwise
*/
private boolean findPath(Point location) {
// We have reached the end point, and solved the maze
if (location.equals(maze.getEndCoords())) {
System.out.println("Found path length: " + pathLength);
maze.setMazeArray(mazeArray);
return true;
}
ArrayList<Point> possibleMoves = new ArrayList<Point>();
// Move Right
possibleMoves.add(new Point(location.x + 1, location.y));
// Down Move
possibleMoves.add(new Point(location.x, location.y - 1));
// Move Left
possibleMoves.add(new Point(location.x - 1, location.y));
// Move Up
possibleMoves.add(new Point(location.x, location.y + 1));
for (Point potentialMove : possibleMoves) {
if (spaceIsFree(potentialMove)) {
// Move to the free space
mazeArray[potentialMove.x][potentialMove.y] = currentPathChar;
// Increment path characters as alphabet
if (currentPathChar == 'z')
currentPathChar = 'a';
else
currentPathChar++;
// Increment path length
pathLength++;
// Find the next path to traverse
if (findPath(potentialMove)) {
return true;
}
// Backtrack, this route doesn't lead to the end
mazeArray[potentialMove.x][potentialMove.y] = Maze.SPACE_CHAR;
if (currentPathChar == 'a')
currentPathChar = 'z';
else
currentPathChar--;
// Decrease path length
pathLength--;
}
}
// Previous space needs to make another move
// We will also return false if the maze cannot be solved.
return false;
}
Run Code Online (Sandbox Code Playgroud)
在第一个区块中,我找到路径并将其分解.写入路径的char [] []数组也会被设置,稍后将其作为结果打印出来.
它运作良好,但我想知道什么是最好的方法来修改它,以便在找到第一个成功的路径后不突破,但继续前进,直到它找到最短路径.
我尝试过这样的事情,修改findPath()方法并添加shortestPath和hasFoundPath变量.第一个指示到目前为止找到的最短路径的长度,以及指示我们是否找到任何路径的hasFoundPath变量.
// We have reached the end point, and solved the maze
if (location.equals(maze.getEndCoords())) {
System.out.println("Found path length: " + pathLength);
// Is this path shorter than the previous?
if (hasFoundPath && pathLength < shortestPathLength) {
maze.setMazeArray(mazeArray);
shortestPathLength = pathLength;
} else if (!hasFoundPath) {
hasFoundPath = true;
maze.setMazeArray(mazeArray);
shortestPathLength = pathLength;
}
//return true;
}
Run Code Online (Sandbox Code Playgroud)
但是我无法让它将mazeArray设置为它可能找到的任何最短路径的正确值.
任何指导将不胜感激:)谢谢
spaceIsFree()方法只需确保向上/向左/向下/向右坐标有效,然后再移动它们.所以它确保char是'_'或'E'并且它不会超出范围.
您的代码似乎执行深度优先搜索(DFS).要找到最短路径,您需要切换到广度优先搜索(BFS).通过在现有代码中添加一些变量,您无法做到这一点.它需要重写您的算法.
将DFS转换为BFS的一种方法是去除递归并切换到使用显式堆栈来跟踪到目前为止您访问过的节点.在搜索循环的每次迭代中,您(1)从堆栈中弹出一个节点; (2)检查该节点是否是解决方案; (3)将每个孩子推到堆叠上.在伪代码中,它看起来像:
深度优先搜索
stack.push(startNode)
while not stack.isEmpty:
node = stack.pop()
if node is solution:
return
else:
stack.pushAll(node.children)
Run Code Online (Sandbox Code Playgroud)
如果然后将堆栈切换到队列,这将隐式变为BFS,并且BFS自然会找到最短路径.
广度优先
queue.add(startNode)
while not queue.isEmpty:
node = queue.remove()
if node is solution:
return
else:
queue.addAll(node.children)
Run Code Online (Sandbox Code Playgroud)
另外两点说明:
上述算法适用于树木:没有环的迷宫.如果你的迷宫有循环,那么你需要确保你没有重新访问你已经看过的节点.在这种情况下,您需要添加逻辑以跟踪所有已访问过的节点,并避免第二次将它们添加到堆栈/队列中.
如上所述,这些算法将找到目标节点,但他们不记得在那里获得它们的路径.添加它是读者的练习.