我做了一个递归算法来找到迷宫的解决方案,格式如下
###S###
##___##
##_#_##
#__#_##
#E___##
其中一个“#”代表一堵墙,“#”代表一个开放空间(可以自由移动)。”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;
}
在第一个街区,我找到了那条路并把它打开。还设置了写有路径的char[][]数组,该数组随后作为结果打印出来。
它工作得很好,但是我想知道什么是最好的方法来修改它,使它在找到第一条成功的路径后不爆发,而是继续前进,直到找到最短的路径。
我尝试做了这样的事情,修改findPath()方法并添加一个最短路径和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;
}
但我没能让它将Mazarray设置为它可能找到的任何最短路径的正确值。
任何指导将不胜感激:)谢谢
spaceIsFree()方法只是确保上/左/下/右坐标在移动到它们之前是有效的。因此它确保char是“_”或“E”并且没有越界。
这是我想出的BFS搜索解决方案。它将起点标记为“1”,然后将它可以到达的每个相邻点标记为“2”,将可以到达的每个相邻点标记为“3”,依此类推。
然后从末尾开始,使用递减的“level”值向后移动,从而得到最短路径。
private LinkedList<Point> findShortestPath(Point startLocation) {
// This double array keeps track of the "level" of each node.
// The level increments, starting at the startLocation to represent the path
int[][] levelArray = new int[mazeArray.length][mazeArray[0].length];
// Assign every free space as 0, every wall as -1
for (int i=0; i < mazeArray.length; i++)
for (int j=0; j< mazeArray[0].length; j++) {
if (mazeArray[i][j] == Maze.SPACE_CHAR || mazeArray[i][j] == Maze.END_CHAR)
levelArray[i][j] = 0;
else
levelArray[i][j] = -1;
}
// Keep track of the traversal in a queue
LinkedList<Point> queue = new LinkedList<Point>();
queue.add(startLocation);
// Mark starting point as 1
levelArray[startLocation.x][startLocation.y] = 1;
// Mark every adjacent open node with a numerical level value
while (!queue.isEmpty()) {
Point point = queue.poll();
// Reached the end
if (point.equals(maze.getEndCoords()))
break;
int level = levelArray[point.x][point.y];
ArrayList<Point> possibleMoves = new ArrayList<Point>();
// Move Up
possibleMoves.add(new Point(point.x, point.y + 1));
// Move Left
possibleMoves.add(new Point(point.x - 1, point.y));
// Down Move
possibleMoves.add(new Point(point.x, point.y - 1));
// Move Right
possibleMoves.add(new Point(point.x + 1, point.y));
for (Point potentialMove: possibleMoves) {
if (spaceIsValid(potentialMove)) {
// Able to move here if it is labeled as 0
if (levelArray[potentialMove.x][potentialMove.y] == 0) {
queue.add(potentialMove);
// Set this adjacent node as level + 1
levelArray[potentialMove.x][potentialMove.y] = level + 1;
}
}
}
}
// Couldn't find solution
if (levelArray[maze.getEndCoords().x][maze.getEndCoords().y] == 0)
return null;
LinkedList<Point> shortestPath = new LinkedList<Point>();
Point pointToAdd = maze.getEndCoords();
while (!pointToAdd.equals(startLocation)) {
shortestPath.push(pointToAdd);
int level = levelArray[pointToAdd.x][pointToAdd.y];
ArrayList<Point> possibleMoves = new ArrayList<Point>();
// Move Right
possibleMoves.add(new Point(pointToAdd.x + 1, pointToAdd.y));
// Down Move
possibleMoves.add(new Point(pointToAdd.x, pointToAdd.y - 1));
// Move Left
possibleMoves.add(new Point(pointToAdd.x - 1, pointToAdd.y));
// Move Up
possibleMoves.add(new Point(pointToAdd.x, pointToAdd.y + 1));
for (Point potentialMove: possibleMoves) {
if (spaceIsValid(potentialMove)) {
// The shortest level will always be level - 1, from this current node.
// Longer paths will have higher levels.
if (levelArray[potentialMove.x][potentialMove.y] == level - 1) {
pointToAdd = potentialMove;
break;
}
}
}
}
return shortestPath;
}
spaceIsValid()只是确保空间不超出边界。
您的代码似乎执行深度优先搜索(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)
如果您随后将堆栈切换到队列,这将隐式地成为BFS,并且BFS自然会找到最短路径。
宽度优先锯齿
queue.add(startNode)
while not queue.isEmpty:
node = queue.remove()
if node is solution:
return
else:
queue.addAll(node.children)
还有几点需要注意:
>
上述算法适用于树:没有循环的迷宫。如果您的迷宫有循环,那么您需要确保不会重新访问您已经看到的节点。在这种情况下,您需要添加逻辑来跟踪所有已经访问过的节点,并避免第二次将它们添加到堆栈/队列中。
如前所述,这些算法会找到目标节点,但它们不记得将它们带到那里的路径。补充这是读者的练习。
最近,我一直在尝试编写一些递归迷宫代码,它可以返回迷宫中的最短路径。如果迷宫中没有路径,那么代码将返回-1。 例如,对于董事会: 其中S是迷宫的起点,W代表一堵墙,X代表所需的目的地,和-代表一个可用的路径点。输出将是: 对于董事会: 输出将是 这一切都是通过一个board类实现的,该类接受一个字符串和迷宫的尺寸,一个返回最短路径的检查函数,以及一个返回最短路径的win函数,如果没有路径,则返回-
我在用递归解迷宫。我的矩阵是这样的 这是更大矩阵的原型。我的求解递归方法如下所示 你们可以注意到,这里我返回一个布尔值,如果我找到一条路径,它应该会给我一个真值。但它总是给我错误的答案。我不确定我在递归方法中犯的逻辑错误。方法如下 endX=3;endY=10;
我正在尝试寻找到EndPotion的路径。这是一个递归函数。请帮助,我要自杀了。 这是给定的地图 我想递归地使用GetPath来到达上面地图中的EndPotion。参数是当前位置、结束位置和地图。对于这个例子,起始位置是(0,0)和结束,EndPotionis是(0,3),右上角。0代表墙壁,1代表路径。 我需要返回一个包含有效点的arraylist到结束位置。虽然我的数组大小始终为0,并且基本大
我得到了一些构建迷宫的代码,以及任何其他需要的东西,抽象迷宫类包含一个抽象方法“makeMove(int row,int col)”。这是我试图编写的解决迷宫的方法,向左、向右、向上、向下移动。 我刚刚开始做这件事,下面是我到目前为止的全部资料。 好的,我让代码运行到不再出现错误的地方。 感谢所有的帮助。
(这不是一个复制品)我们有一个2D迷宫,四面都有X,还有内部的方块<迷宫的所有这些特征都存储在2D数组中。程序必须找到从开始“S”到目标“G”的路径。为此,将使用一个名为“solve(int row,int col)”的布尔方法,并使用“S”的行和列索引初始化该方法。算法必须是递归的。如果它能够找到通往“G”的路径,那么它应该返回true,否则返回false。下面是我试图解决这个问题的方法,它显示
给定一个填充了0和1的二维字符数组,其中0代表一堵墙,1代表一条有效路径,我开发了一个名为findPath(int r,int c)的递归方法,用于在标有“x”的迷宫中找到出口。该方法接收迷宫的当前行和列,并通过N、E、S、W方向,直到找到有效路径,并用“”标记该有效路径。假设所有方向都被一堵墙挡住,那么该方法假设是回溯,直到情况不再如此,然后用“F”标记该路径,以表示坏路径。 现在我不明白为什么