如何在java中使用2d数组迷宫查找路径
这里, S=起点(2,2) B=块 O=打开 X=退出 我想做一个迷宫,检查北、西、东、南。如果X在附近,它将返回程序。如果没有,则检查起点周围是否有“O”,并递归传递新的起点。如果无路可走,且未找到“X”,则将返回原始起点(2,2),并检查西部、东部和南部 节目结束后,我得到:如何在java中使用2d数组迷宫查找路径,java,recursion,flood-fill,Java,Recursion,Flood Fill,这里, S=起点(2,2) B=块 O=打开 X=退出 我想做一个迷宫,检查北、西、东、南。如果X在附近,它将返回程序。如果没有,则检查起点周围是否有“O”,并递归传递新的起点。如果无路可走,且未找到“X”,则将返回原始起点(2,2),并检查西部、东部和南部 节目结束后,我得到: 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 但是,我希望递归后的输出是: B B B B B B B B + B B B + + B B O +
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
但是,我希望递归后的输出是:
B B B B B
B B B + B
B B + + B
B O + B B
B B X B B
这是我现在的代码:
B B B B B
B B B - B
B B + - B
B O + B B
B B X B B
使用全局变量(标志)确定是否找到了正确的路径
例如:
BBBBB
BBOOB
XOBOB
BSOBB
BBBBB
BBBBB
BBOOB
X+BOB ( It should stop right here, because there is X around it.)
BSOBB
BBBBB
BBBBB
BBOOB
X+BOB (but, somehow it go to the right of the startpoint and mark the 'O' to '+'
BS+BB
BBBBB
公共类您的类{
静态布尔值found=false;//全局标志
//您现有的代码
公共静态void Find_Path(char[][]迷宫、int startX、int startY){
// ....
对于(int i=0;i<4;i++){
// ...
如果(迷宫[后X][后y]=='X'){
found=true;//找到路径
返回;
}
}
对于(int i=0;i<4;i++){
// ...
if(find)//在前面的递归调用中已找到路径;无需再搜索
返回;
否则{//尚未找到路径,必须继续搜索
如果(迷宫[后X][后Y]=='O'){
找到路径(迷宫、后x、后y);
如果(!found){//未找到路径
迷宫[afterX][afterY]='-';
}
}
}
}
}
}
您正在寻找的算法称为广度优先搜索和深度优先搜索。你会遇到的一个问题是,你的迷宫中是否存在一个循环。例如,如果你有这个会发生什么
public class YourClass{
static boolean found = false; // the global flag
// your existing code
public static void Find_Path(char[][] maze, int startX, int startY){
// ....
for(int i = 0; i < 4 ; i++){
// ...
if(maze[afterX][afterY] == 'X'){
found = true; // path found
return;
}
}
for(int i = 0; i < 4 ; i++){
// ...
if(found) // path already found in earlier recursive call; no need to search anymore
return;
else{ // path not found yet, have to continue searching
if(maze[afterX][afterY] == 'O'){
Find_Path(maze, afterX, afterY);
if(!found){ // path not found
maze[afterX][afterY] = '-';
}
}
}
}
}
}
然后,算法可能会陷入一个无法逃脱的循环中
解决此问题的经典方法是使用另一个数据结构“着色”顶点,该数据结构表示以前是否访问过顶点
本次麻省理工开放式课程可能会为您指明正确的方向:
不过,要直接回答您的问题,请考虑基本情况。当你找到X时,是什么阻止了循环的旋转?在当前状态下,停止迭代/递归的唯一原因似乎是您没有地方可以查看。您需要某种类型的变量来告诉第二个for循环停止搜索。当问题被提出时,此解决方案应该有效:
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
例如@William John Howard设计的迷宫没有解决方案:
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]
输出为:
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]));
}
}
}
{'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'}
如您所见,出口有多条正确路径,NE、EN、WNE、SENN、SWNNEE、ESWWNNEE(此算法选择的路径是因为方向优先级)
我认为您发布的代码中缺少的主要内容是跟踪当前路径的方法,以及在遇到死胡同时进行回溯的方法。在问题中,OP试图使用它来解决迷宫。谢谢,但退出点前面的“O”int将变为“-”,pl,请检查一下这个问题,了解我在说什么,把所有的“O”都变成“-”不是所有的
O
;只有属于错误路径的O
-s。当找到X
时,found
将变为true
-这将停止任何进一步的O
->-
转换。我在代码中犯了一个错误-我没有将found
声明为静态。现在看看这是否如您预期的那样有效。对于某些情况,它会将所有的“O”变成“+”,您能解释一下原因吗?像这个例子一样,我提出了我的问题。
{'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]