public class Main {
public static void main(String[] args) {
System.out.println("Hello, World!");
//创建迷宫数组
int[][] miGong = new int[8][8];
for (int i = 0; i < miGong.length; i++) {
miGong[i][0] = 1;
miGong[i][7] = 1;
}
for (int j = 0; j < miGong[0].length; j++) {
miGong[0][j] = 1;
miGong[7][j] = 1;
}
//miGong[2][1] = 1;
miGong[3][2] = 1;
miGong[3][3] = 1;
miGong[3][4] = 1;
miGong[6][5] = 1;
miGong[5][5] = 1;
miGong[4][5] = 1;
miGong[3][5] = 1;
//打印迷宫数组
System.out.println("=======初始迷宫数组========");
for(int i = 0; i < miGong.length; i++) {
for (int j = 0 ;j < miGong[i].length; j++) {
System.out.print(miGong[i][j] + " ");
}
System.out.println();
}
T t = new T();
t.findway(miGong, 1,1);
System.out.println("========查找出路数组=========");
for(int i = 0; i < miGong.length; i++) {
for (int j = 0 ;j < miGong[i].length; j++) {
System.out.print(miGong[i][j] + " ");
}
System.out.println();
}
}
}
class T {
//找迷宫出路的方法 ij为当前位置
boolean findway (int[][] map, int i, int j) {
// 6,6为出口位置,若置为2,说明已经找到
// 也是该方法递归过程中调用的最深的栈
// 决定其它位置findway是否真的能返回true
if (map[6][6] == 2) return true;
if (map[i][j] == 0) {
System.out.println("暂时置2 i:"+ i + " " + "j:"+ j);
map[i][j] = 2;
if(findway(map, i+1, j) || findway(map, i, j+1) ||
findway(map, i-1, j) || findway(map, i, j-1)) {
System.out.println("返回true i:"+ i + " " + "j:"+ j);
return true;
} else {
map[i][j] = 3;
System.out.println("四周不通,置3返回false i:"+ i + " " + "j:"+ j);
return false;
}
} else /*此时说明ij这个位置的值为 1/2/3;*/{
System.out.println("遇" + map[i][j] + "直接返回false i:"+ i + " " + "j:"+ j);
return false;
}
}
}
理解递归实现迷宫问题的难点在于findWay函数的返回值到底什么时候真正是true, 什么时候是false。网上给的视频都讲得比较短,这段代码我详细输出了递归调用的整个运行过程。也许能帮助理解迷宫查找出路的运行过程。以下是详细输出结果。
Hello, World!
=======初始迷宫数组========
1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 1
1 0 0 0 0 0 0 1
1 0 1 1 1 1 0 1
1 0 0 0 0 1 0 1
1 0 0 0 0 1 0 1
1 0 0 0 0 1 0 1
1 1 1 1 1 1 1 1
暂时置2 i:1 j:1
暂时置2 i:2 j:1
暂时置2 i:3 j:1
暂时置2 i:4 j:1
暂时置2 i:5 j:1
暂时置2 i:6 j:1
遇1直接返回false i:7 j:1
暂时置2 i:6 j:2
遇1直接返回false i:7 j:2
暂时置2 i:6 j:3
遇1直接返回false i:7 j:3
暂时置2 i:6 j:4
遇1直接返回false i:7 j:4
遇1直接返回false i:6 j:5
暂时置2 i:5 j:4
遇2直接返回false i:6 j:4
遇1直接返回false i:5 j:5
暂时置2 i:4 j:4
遇2直接返回false i:5 j:4
遇1直接返回false i:4 j:5
遇1直接返回false i:3 j:4
暂时置2 i:4 j:3
暂时置2 i:5 j:3
遇2直接返回false i:6 j:3
遇2直接返回false i:5 j:4
遇2直接返回false i:4 j:3
暂时置2 i:5 j:2
遇2直接返回false i:6 j:2
遇2直接返回false i:5 j:3
暂时置2 i:4 j:2
遇2直接返回false i:5 j:2
遇2直接返回false i:4 j:3
遇1直接返回false i:3 j:2
遇2直接返回false i:4 j:1
四周不通,置3返回false i:4 j:2
遇2直接返回false i:5 j:1
四周不通,置3返回false i:5 j:2
四周不通,置3返回false i:5 j:3
遇2直接返回false i:4 j:4
遇1直接返回false i:3 j:3
遇3直接返回false i:4 j:2
四周不通,置3返回false i:4 j:3
四周不通,置3返回false i:4 j:4
遇3直接返回false i:5 j:3
四周不通,置3返回false i:5 j:4
遇2直接返回false i:6 j:3
四周不通,置3返回false i:6 j:4
遇3直接返回false i:5 j:3
遇2直接返回false i:6 j:2
四周不通,置3返回false i:6 j:3
遇3直接返回false i:5 j:2
遇2直接返回false i:6 j:1
四周不通,置3返回false i:6 j:2
遇2直接返回false i:5 j:1
遇1直接返回false i:6 j:0
四周不通,置3返回false i:6 j:1
遇3直接返回false i:5 j:2
遇2直接返回false i:4 j:1
遇1直接返回false i:5 j:0
四周不通,置3返回false i:5 j:1
遇3直接返回false i:4 j:2
遇2直接返回false i:3 j:1
遇1直接返回false i:4 j:0
四周不通,置3返回false i:4 j:1
遇1直接返回false i:3 j:2
遇2直接返回false i:2 j:1
遇1直接返回false i:3 j:0
四周不通,置3返回false i:3 j:1
暂时置2 i:2 j:2
遇1直接返回false i:3 j:2
暂时置2 i:2 j:3
遇1直接返回false i:3 j:3
暂时置2 i:2 j:4
遇1直接返回false i:3 j:4
暂时置2 i:2 j:5
遇1直接返回false i:3 j:5
暂时置2 i:2 j:6
暂时置2 i:3 j:6
暂时置2 i:4 j:6
暂时置2 i:5 j:6
暂时置2 i:6 j:6
返回true i:6 j:6
返回true i:5 j:6
返回true i:4 j:6
返回true i:3 j:6
返回true i:2 j:6
返回true i:2 j:5
返回true i:2 j:4
返回true i:2 j:3
返回true i:2 j:2
返回true i:2 j:1
返回true i:1 j:1
========查找出路数组=========
1 1 1 1 1 1 1 1
1 2 0 0 0 0 0 1
1 2 2 2 2 2 2 1
1 3 1 1 1 1 2 1
1 3 3 3 3 1 2 1
1 3 3 3 3 1 2 1
1 3 3 3 3 1 2 1
1 1 1 1 1 1 1 1
因为设置的路障和先下→右→上→左的查找顺序,使得查找过程中经历了一段死路,研究这段能帮助加深理解。
输出结果中置3的就是死路,从(4,2)开始,回溯到(3,1)都置为3了。在这之前这些位置都是2,但因为到(4,2)的时候,四周不通,无路可走,就像贪吃蛇遇到自己的尾巴一样。下面的蓝线是这一段的查找路线。
于是回溯到(3,1)的时候,对(2,1)来说,findWay(3,1)刚刚判断结束为false,按照规则,要调用findWay(2,2)了,于是后面继续查找,一路暂时置2,直到找到(6,6)时,才真正开始返回true,按照来时的路线,一路回溯到(1,1)。