递归之迷宫回溯问题
- 用二维数组表示迷宫
- 用1表示围墙以及障碍物,
- 用2表示该点已经走过,经过该点,同时2表示的是该条路径是通路
- 用3表示该点也走过,但是该条路径是死路
- 走迷宫是给点一个选择路径的方向
基本代码:
package maze.migong;
public class Maze {
public static void main(String[] args) {
//创建一个二维数组,用来模拟迷宫---地图
int [][] map = new int [11][12];
//使用1表示墙,地图四周都是用墙围起来的
for(int i = 0 ; i < 12;i ++){
map[0][i] = 1;
map[10][i] = 1;
}
for (int i = 0; i < 11; i++){
map[i][0] = 1;
map[i][11] = 1;
}
//设置障碍物
for (int i = 0;i < 4;i ++){
map[5][i] = 1;
map[i][8] = 1;
map[i][6] = 1;
map[2][i] = 1;
map[i + 4][5] = 1;
}
//输出地图
for(int i = 0 ;i < 11;i ++){
for(int j = 0;j < 12;j ++ ){
System.out.print(" " + map[i][j]);
}
System.out.println();
}
}
/**
*
* @param map map表示地图
* @param i
* @param j i和j分别表示开始的坐标
* @return 如果返回值为true表示已经找到路,如果返回false那就是没有找到路
*/
public abstract boolean setWay(int[][] map , int i , int j){
}
}
个人思路分析:
我的代码:
public static boolean setWay(int[][] map , int i , int j){
//这个方法的含义是什么?直接找到到达终点的路吗?
//作为递归方法
if(map[9][10] == 2){
return true;
//到达终点作为递归条件的截止
//那原来的点都是0,你得有赋值的语句才行
}else{
if(map[i][j] == 0){
//如果你传进来的点没有走过,那就以你传进来的点开始走
map[i][j] = 2; //假设该点可以走通,按照下--右--上--左的路径走完
if(map[i - 1][j] == 0 && setWay(map,i + 1,j)){ //向下走
return true;
}else if(map[i][j + 1] == 0 && setWay(map,i,j + 1)){ //向右走
return true;
}else if(map[i + 1][j] == 0 && setWay(map,i -1,j)){ //向上走
return true;
}else if(map[i][j - 1] == 0 && setWay(map,i,j - 1)){ //向左走
return true;
}else{
//说明该点走不通是死路
map[i][j] = 3;
return false;
}
}else if(map[i][j] == 1){
return false;
}else if(map[i][j] == 2){
return false;
}else{
return false;
}
}
}
}
实验结果:
结果分析:
陷入死循环,在应该往下走的路上,没有选择往下。
问题解决:
往左走判断左边是否可以走,往下走判断下面是否可以走,判定语句错误。
第二次运行
步骤图
结果分析:
- 无形间有了试错功能,即使这段路走不通,也会标注为3.
- 同时这里是按照逆序的结果进行输出,他每一次都是调用了另外一个方法进行判断,当最终的值进行返回的时候,就在开始打印
- 如果一条错误的路线很长,他开了那么多栈,发现走不通,再回来,重新走,岂不是浪费很多的空间和时间。每一次的判定都要递归调用开那么多的栈。
教程代码:
public static boolean setWay(int[][] map , int i , int j){
//这个方法的含义是什么?直接找到到达终点的路吗?
//作为递归方法
if(map[9][10] == 2){
return true;
//到达终点作为递归条件的截止
//那原来的点都是0,你得有赋值的语句才行
}else{
if(map[i][j] == 0){
//如果你传进来的点没有走过,那就以你传进来的点开始走
map[i][j] = 2; //假设该点可以走通,按照下--右--上--左的路径走完
if(setWay(map,i - 1,j)){
System.out.print(" 往上走");//向下走
return true;
}else if(setWay(map,i,j + 1)){
System.out.println(" 往右走");//向右走
return true;
}else if(setWay(map,i + 1,j)){
System.out.print(" 往下走");//向上走
return true;
}else if(setWay(map,i,j - 1)){
System.out.println(" 往左走");//向左走
return true;
}else{
//说明该点走不通是死路
System.out.println("此路不通");
map[i][j] = 3;
return false;
}
}else{
//其实只要出现三种情况1、2、3都不可以再走了,所以都是一样的,没必要单列出来
return false;
}
}
}
对比分析与总结:
1.我认为如果把走不通的路径的判定条件放在末尾,会增加程序的递归次数,每走一步都要进行条件判定都要打开很多递归,那干脆在走之前判定一下下一步的值不久可以减少程序运行时间吗?虽然你的值是在当时假定为2,但是判定是否真的为2是要有四个方向的
2. 走过的点暂时标的是2,如果说你选的路没到终点就死了,那么之前暂时标定的2就全部变成3,说明所选的路为死路
3. 方向自己可以提前设定,但是之前走过的路一定不能再走了,怎么让它不在走那?
4. 跳出递归的条件不该只有一种,如果我一开始规定的方向是先左,在右,那么该点在第一行第一段路就陷入了死循环。