【数据结构与算法(Java)】迷宫问题(回溯算法-递归)

1. 递归思路

  1. 基本情况:当前位置 为 终点,设置必要的数字(用于显示),返回true
  2. 向基本情况靠近:上下左右移动,即改变当前位置坐标
  3. 调用自身:将新坐标作为本方法的参数

2. 代码实现

/**
 * 使用回溯算法(递归)解决"迷宫问题"
 */
public class Maze {
    int[][] mazeMap = new int[11][22];
    final int[] startPosition = new int[]{8, 15};
    final int[] endPosition = new int[]{1, 21};

    public Maze() {
        this.generateMazeMap();
        this.mazeMap[this.startPosition[0]][this.startPosition[1]] = 8;
    }

    /**
     * 创建地图
     *      没走过的通路: 0
     *      墙:         1
     *      走过+死路:  2
     *      走过+活路:  3
     *      起点:       7
     *      终点:       9
     */
    private void generateMazeMap() {
        // 起点,终点
        this.mazeMap[this.startPosition[0]][this.startPosition[1]] = 7;
        this.mazeMap[this.endPosition[0]][this.endPosition[1]] = 9;

        // line 1
        for (int i = 0; i < 22; i++) {
            this.mazeMap[0][i] = 1;
        }

        // line 2
        this.mazeMap[1][0] = 1;
        this.mazeMap[1][4] = 1;
        this.mazeMap[1][8] = 1;
        this.mazeMap[1][9] = 1;
        this.mazeMap[1][11] = 1;
        this.mazeMap[1][12] = 1;
        this.mazeMap[1][18] = 1;

        // line 3
        this.mazeMap[2][0] = 1;
        this.mazeMap[2][2] = 1;
        this.mazeMap[2][6] = 1;
        this.mazeMap[2][14] = 1;
        this.mazeMap[2][15] = 1;
        this.mazeMap[2][16] = 1;
        this.mazeMap[2][18] = 1;
        this.mazeMap[2][20] = 1;
        this.mazeMap[2][21] = 1;

        // line 4
        this.mazeMap[3][0] = 1;
        this.mazeMap[3][2] = 1;
        this.mazeMap[3][4] = 1;
        this.mazeMap[3][7] = 1;
        this.mazeMap[3][8] = 1;
        this.mazeMap[3][11] = 1;
        this.mazeMap[3][12] = 1;
        this.mazeMap[3][13] = 1;
        this.mazeMap[3][14] = 1;
        this.mazeMap[3][18] = 1;
        this.mazeMap[3][20] = 1;
        this.mazeMap[3][21] = 1;

        // line 5
        for (int i = 0; i < 10; i++) {
            this.mazeMap[4][i] = 1;
        }
        for (int i = 14; i < 17; i++) {
            this.mazeMap[4][i] = 1;
        }
        this.mazeMap[4][18] = 1;
        this.mazeMap[4][21] = 1;

        // line 6
        this.mazeMap[5][0] = 1;
        this.mazeMap[5][11] = 1;
        this.mazeMap[5][12] = 1;
        this.mazeMap[5][15] = 1;
        this.mazeMap[5][16] = 1;
        this.mazeMap[5][21] = 1;

        // line 7
        for (int i = 0; i < 5; i++) {
            this.mazeMap[6][i] = 1;
        }
        for (int i = 6; i < 6 + 6; i++) {
            this.mazeMap[6][i] = 1;
        }
        for (int i = 15; i < 15 + 5; i++) {
            this.mazeMap[6][i] = 1;
        }
        this.mazeMap[6][21] = 1;

        // line 8
        this.mazeMap[7][0] = 1;
        this.mazeMap[7][6] = 1;
        for (int i = 10; i < 10 + 7; i++) {
            this.mazeMap[7][i] = 1;
        }
        this.mazeMap[7][19] = 1;
        this.mazeMap[7][21] = 1;

        // line 9
        this.mazeMap[8][0] = 1;
        for (int i = 2; i < 9; i++) {
            this.mazeMap[8][i] = 1;
        }
        this.mazeMap[8][17] = 1;
        this.mazeMap[8][21] = 1;

        // line 10
        this.mazeMap[9][0] = 1;
        this.mazeMap[9][17] = 1;
        this.mazeMap[9][19] = 1;
        this.mazeMap[9][20] = 1;
        this.mazeMap[9][21] = 1;

        // line 11
        for (int i = 0; i < 22; i++) {
            this.mazeMap[10][i] = 1;
        }
    }
    // 打印地图
    public void printMaze() {
        for (int line = 0; line < mazeMap.length; line++) {
            for (int column = 0; column < mazeMap[0].length; column++) {
                if (this.mazeMap[line][column] == 0){
                    System.out.printf(" " + "\t"); // 通路
                } else if (this.mazeMap[line][column] == 1) {
                    System.out.printf("♿️" + "\t"); // 墙
                } else if (this.mazeMap[line][column] == 2) {
                    System.out.printf("❌" + "\t"); // 走过的死路
                } else if (this.mazeMap[line][column] == 7) {
                    System.out.printf("🏀" + "\t"); // 起点
                } else if (this.mazeMap[line][column] == 9) {
                    System.out.printf("🏁" + "\t"); // 终点
                } else if (this.mazeMap[line][column] == 3){
                    System.out.printf("🍀" + "\t"); // 走过的通路
                } else {
                    throw new RuntimeException("map error");
                }
            }
            System.out.println();
        }
    }

    /**
     * 探索地图
     * 上 -> 下 -> 左 -> 右
     * @return - 是否有出路
     */
    public boolean hasSolution(int line, int column) {
        if (this.mazeMap[line][column] == 8) {
            this.mazeMap[line][column] = 0;
        }
        // 若 当前标识为 0,为未走的通路,开始探索
        if (this.mazeMap[line][column] == 0){
            // 假设该店可以走通:设置为 3
            this.mazeMap[line][column] = 3;
            // 向下
            if (hasSolution(line + 1, column)) {
                return true;
            }
            // 向右
            else if (hasSolution(line, column + 1)) {
                return true;
            }
            // 向上
            else if (hasSolution(line - 1, column)) {
                return true;
            }
            // 向左
            else if (hasSolution(line, column - 1)) {
                return true;
            }
            // 走不通,设置为 2,返回false
            else {
                this.mazeMap[line][column] = 2;
                return false;
            }
        }
        // 标识 9,当前为终点,设置为 3,返回true
        else if (this.mazeMap[line][column] == 9) {
            this.mazeMap[line][column] = 3;
            this.mazeMap[this.startPosition[0]][this.startPosition[1]] = 7;
            this.mazeMap[this.endPosition[0]][this.endPosition[1]] = 9;
            return true;
        }
        // 标识 1,当前为墙,返回false
        else {
            return false;
        }
    }
}

3. 探索结果图示

迷宫图示

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值