由于提出问题,这个解决方案应该工作:
import java.util.Arrays;
public class TwoDSolver {
private char[][] maze;
private String currPath;
private int currX;
private int currY;
private boolean unsolvable;
public static void main(String[] args) {
char[][] customMaze = {
{'B', 'B', 'B', 'B', 'B'},
{'B', 'B', 'B', 'O', 'B'},
{'B', 'B', 'S', 'O', 'B'},
{'B', 'O', 'O', 'B', 'B'},
{'B', 'B', 'X', 'B', 'B'}
};
String startPath = "";
int startX = 2;
int startY = 2;
TwoDSolver solver = new TwoDSolver(customMaze, startX, startY, startPath, false);
// place a plus at the start point
solver.placePlus();
solver.solveMaze();
if (solver.unsolvable) {
System.out.println("The maze is unsolvable");
} else {
System.out.println("Solved, A correct path is: " + solver.currPath);
}
solver.printMaze();
}
// constructor
TwoDSolver(char[][]aMaze, int stX, int stY, String currentPath, boolean noSolution) {
maze = aMaze;
currX = stX;
currY = stY;
currPath = currentPath;
unsolvable = noSolution;
}
// indicate taken path
void placePlus() {
maze[currX][currY] = '+';
}
// for backtracking
void placeMinus() {
maze[currX][currY] = '-';
}
// solve
// priority in this order East, West, South, North
void solveMaze() {
// check for a win
if (checkForWin()) {
return;
}
// No win, so let's check for an opening
// check east
if (currY + 1 < maze[currX].length && checkForOpen(currX, currY + 1)) {
currY++;
placePlus();
currPath += "E"; // Append East to our current path
// recursive call continue searching
solveMaze();
// check west
} else if (currY - 1 >= 0 && checkForOpen(currX, currY - 1)) {
currY--;
placePlus();
currPath += "W";
solveMaze();
// check south
} else if (currX + 1 < maze.length && checkForOpen(currX + 1, currY)) {
currX++;
placePlus();
currPath += "S";
solveMaze();
// check north
} else if (currX - 1 >= 0 && checkForOpen(currX - 1, currY)) {
currX--;
placePlus();
currPath += "N";
solveMaze();
} else { // we've hit a dead end, we need to backtrack
if (currPath.length() == 0) {
// we're back at the starting point, the maze is unsolvable
unsolvable = true;
return;
} else {
// we've reached a dead end, lets backtrack
placeMinus();
backTrack();
}
}
}
// see if the spot at a give x, y is open
boolean checkForOpen(int x, int y) {
return maze[x][y] == 'O';
}
// see if any of the surrounding spots are the exit
boolean checkForWin() {
// make sure to protect against out of bounds as well
return ((currY + 1 < maze[currX].length && maze[currX][currY + 1] == 'X') ||
(currY - 1 >= 0 && maze[currX][currY - 1] == 'X') ||
(currX + 1 < maze[currX].length && maze[currX + 1][currY] == 'X') ||
(currX -1 >= 0 && maze[currX -1][currY] == 'X'));
}
void backTrack() {
// sanity chek currPath.length() should always be > 0 when we call backTrack
if (currPath.length() > 0) {
placeMinus();
switch (currPath.charAt(currPath.length() - 1)) {
case 'E':
currY--;
break;
case 'W':
currY++;
break;
case 'S':
currX--;
break;
case 'N':
currX++;
break;
}
currPath = currPath.substring(0, currPath.length()-1);
solveMaze();
}
}
void printMaze() {
for (int i = 0; i < maze.length; i++) {
System.out.println(Arrays.toString(maze[i]));
}
}
}
对于示例迷宫输出:
Solved, A correct path is: S
[B, B, B, B, B]
[B, B, B, -, B]
[B, B, +, -, B]
[B, O, +, B, B]
[B, B, X, B, B]
对于由@William霍华德旨意的例子迷宫是无解:
{'B', 'B', 'B', 'B', 'B'},
{'B', 'O', 'O', 'O', 'B'},
{'B', 'O', 'S', 'O', 'B'},
{'B', 'O', 'O', 'O', 'B'},
{'B', 'B', 'B', 'B', 'B'}
的输出是:
The maze is unsolvable
[B, B, B, B, B]
[B, -, -, -, B]
[B, -, +, -, B]
[B, -, -, -, B]
[B, B, B, B, B]
有一点要注意这个解决方案,并接近问题的思考方式: 这将不会提供给出口
该解决方案顺序优先最短路径:东,西, 南北。
这里是我的意思的例子:
开始迷宫:
{'B', 'B', 'B', 'X', 'B'},
{'B', 'O', 'O', 'O', 'B'},
{'B', 'O', 'S', 'O', 'B'},
{'B', 'O', 'O', 'O', 'B'},
{'B', 'B', 'B', 'B', 'B'}
输出:
Solved, A correct path is: ESWWNNEE
[B, B, B, X, B]
[B, +, +, +, B]
[B, +, +, +, B]
[B, +, +, +, B]
[B, B, B, B, B]
正如你可以看到有到出口,NE多个正确的路径, EN,WNEE,SENN,SWNNEE,ESWWNNEE(这是算法优先选择的一个)。
我认为您从发布的代码中遗漏的主要内容是一种记录您当前路径和回溯的方式,当您遇到死胡同时。
谢谢,但出口点的'O'int前将转向' - ',, PL,放松检查问题知道我在说什么 –
实际上它将所有的'O'都变成' - ' –
不是所有'O';只是那些错误路径中的'O'-s。当找到'X'时,'found'将变为'true' - 这将停止进一步的'O' - >'-'转换。 – Muntasir