由於提出問題,這個解決方案應該工作:
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