递归解决迷宫问题

递归解决迷宫问题

什么是递归?

递归,就是在运行的过程中调用自己。
构成递归需具备的条件:

  1. 子问题须与原始问题为同样的事,且更为简单;
  2. 不能无限制地调用本身,须有个出口,化简为非递归状况处理。

解决什么问题?

在这里插入图片描述
这是一个迷宫,编写一个程序,使其找到一条从起点通往终点路,怎么去实现呢?

实现前提说明

如上图,是一个8*7的表格,在里面找路,我们首先得构建出这个迷宫。
说明:
1、定义一个二维数组map来表示这个迷宫。
2、i,j表示从地图什么地方开始出发。
3、如果能走到map[6][5]位置,则说明通路找到。
4、约定:当map[i][j]为0表示该点没有走过,当为1表示墙,2表示通路可以走,3表示该点已经走过,但走不通。
5、在走迷宫时,需要确定一个策略,走路顺序为:下->右->上->左,如果该点下右上左都走不通,在回溯。
在这里插入图片描述

问题解决

我们首先构建迷宫二维数组

int[][] map = new int[8][7];
        //设置围墙,1表示墙
        for (int i = 0; i < map.length; i++) {
            map[i][0] = 1;
            map[i][map[0].length - 1] = 1;
        }
        for (int i = 0; i < map[0].length; i++) {
            map[0][i] = 1;
            map[map.length - 1][i] = 1;
        }
        //设置挡板,1表示墙
        map[6][2] = 1;
        map[6][4] = 1;

我们输出看一下:

1 1 1 1 1 1 1 
1 0 0 0 0 0 1 
1 0 0 0 0 0 1 
1 0 0 0 0 0 1 
1 0 0 0 0 0 1 
1 0 0 0 0 0 1 
1 0 1 0 1 0 1 
1 1 1 1 1 1 1 

我们定义一个递归方法setWay,参数是一个二维数组和当前所在位置的i,j。
1、我们首先判断现在所处的位置是否是终点map[6][5],是就返回true。
2、如果不为终点,我们就进行我们的策略走法:
2.1、如果当前这个点为0,证明还没有走,首先将这个点赋值为2,然后进行递归,把位置向下移动一位setWay(map, i + 1, j),i+1就是向下走,j+1就是向右走,i-1就是向上走,j-1就是向左走,我们,向下移动发现这个点不为0,可能是1、2、3,返回false,然后回溯到上一次调用,然后开始向右走,还走不通向上向左,都走不通把这个点设置为3,回溯到上一个点,开始向右走,就这样直到找到出口,或者没有出口全图走一遍。

代码实现

    public static boolean setWay(int[][] map, int i, int j) {
        if (map[6][5] == 2) {//通路已经找到,直接返回true
            return true;
        } else {
            if (map[i][j] == 0) {//如果当前这个点还没走过
                //按照策略 下->右->上->左 走
                map[i][j] = 2;
                if (setWay(map, i + 1, j)) {//向下走
                    return true;
                } else if (setWay(map, i, j + 1)) {//向右走
                    return true;
                } else if (setWay(map, i - 1, j)) {//向上走
                    return true;
                } else if (setWay(map, i, j - 1)) {//向左走
                    return true;
                } else {//都走不了,证明是死路,标注为3
                    map[i][j] = 3;
                    return false;
                }
            } else {//如果map[i][j] !=0,可能是1、2、3
                return false;
            }
        }
    }

测试结果

找到路的状态:
1 1 1 1 1 1 1 
1 2 0 0 0 0 1 
1 2 0 0 0 0 1 
1 2 0 0 0 0 1 
1 2 0 0 0 0 1 
1 2 2 2 2 2 1 
1 3 1 3 1 2 1 
1 1 1 1 1 1 1 

实话说,递归并不好理解,大家可以画一个图,一步一步跟着代码走一遍就懂了。

全部代码:

public class MiGong {
    public static void main(String[] args) {
        int[][] map = new int[8][7];
        //设置围墙,1表示墙
        for (int i = 0; i < map.length; i++) {
            map[i][0] = 1;
            map[i][map[0].length - 1] = 1;
        }
        for (int i = 0; i < map[0].length; i++) {
            map[0][i] = 1;
            map[map.length - 1][i] = 1;
        }
        //设置挡板,1表示墙
        map[6][2] = 1;
        map[6][4] = 1;
//        map[6][4] = 1;
//        map[5][4] = 1;
//        map[5][5] = 1;
        //输出地图
        System.out.println("地图原始状态:");
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[0].length; j++) {
                System.out.print(map[i][j] + " ");
            }
            System.out.println();
        }
        if (setWay(map, 1, 1)) {
            //输出地图
            System.out.println("找到路的状态:");
            for (int i = 0; i < map.length; i++) {
                for (int j = 0; j < map[0].length; j++) {
                    System.out.print(map[i][j] + " ");
                }
                System.out.println();
            }
        } else {
            //输出地图
            System.out.println("找不到路的状态:");
            for (int i = 0; i < map.length; i++) {
                for (int j = 0; j < map[0].length; j++) {
                    System.out.print(map[i][j] + " ");
                }
                System.out.println();
            }
            System.out.println("找不到路哦!");
        }
    }

    /**
     * 使用递归回溯来给小球找路
     * 说明:
     * 1.map 表示地图
     * 2.i,j 表示从地图什么地方开始出发
     * 3.如果小球能到map[6][5]位置,则说明通路找到
     * 4.约定:当map[i][j]为0表示该点没有走过 当为1表示墙,2表示通路可以走,3表示该点已经走过,但是走不通
     * 5.在走迷宫时,需要确定一个策略,下->右->上->左,如果该点走不通,在回溯
     *
     * @param map 表示地图
     * @param i   从哪个位置开始找
     * @param j
     * @return 如果找到通路返回true,否则返回false
     */
    public static boolean setWay(int[][] map, int i, int j) {
        if (map[6][5] == 2) {//通路已经找到,直接返回true
            return true;
        } else {
            if (map[i][j] == 0) {//如果当前这个点还没走过
                //按照策略 下->右->上->左 走
                map[i][j] = 2;
                if (setWay(map, i + 1, j)) {//向下走
                    return true;
                } else if (setWay(map, i, j + 1)) {//向右走
                    return true;
                } else if (setWay(map, i - 1, j)) {//向上走
                    return true;
                } else if (setWay(map, i, j - 1)) {//向左走
                    return true;
                } else {//都走不了,证明是死路,标注为3
                    map[i][j] = 3;
                    return false;
                }
            } else {//如果map[i][j] !=0,可能是1、2、3
                return false;
            }
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值