Java 算法之迷宫(简单实现)

本文介绍了一种简单的递归算法来解决走迷宫问题,从起点到终点寻找一条可行路径。通过在二维数组中用1表示墙壁,0表示路径,并设置边界条件,采用递归方式尝试上下左右四个方向移动。当遇到死胡同时,递归返回并尝试其他路线。最终找到出口并输出路径。代码示例展示了整个过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在学习算法,又又看到了一个挺有趣的题目,就是走迷宫,就写了一篇简单实现走迷宫的算法,就只是找到一条出路,你问为啥不写复杂一点,因为作者想留给你们写(就是懒得考虑那么多dog)。如果有小伙伴需要考虑复杂一些的,比如输出多条路线,或者多条路线找到最简等要求,可以给我留言,我在出一个2.0迷宫(正大光明水文章)。

说明

走迷宫是递归求解的基本题型,我们在二维阵列中使用1表示迷宫墙壁,使用0表示行走的路径,找到从入口至出口的路线。
从第一行的第一个元素为入口,走到最后一行的最后一个元素为出口

  0  1	1	1                                   
  0  0	0	1
  0  1	0	0
  0  1	1	0	
  *  1	1	1             这个就是路线                      
  *  *	*	1
  0  1	*	*
  0  1	1	*	

提示:下一步进入我们最喜欢的解题思路环节。
在这里插入图片描述

解题思路

上面我们已经画出了行走路线,但是要怎么才能实现那?

1: 第一步

我们理所应当要先考虑怎么实现行走,这个很简单,我们只需要在原先的二维坐标上面进行操作,比如(a,b),我们给 a+1 就实现了向下,a-1 向上 ,b+1 向右,b-1 向左,这样就解决了行走。

2: 第二步

我们需要考虑边界问题,如果你不考虑,那么恭喜你将喜提ArrayIndexOutOfBoundsException异常(数组索引越界异常)。因为是二维数组嘛,所以最小我们要考虑大于等于0,最大只能是小于数组的长度(数组的行和列)

3: 第三步 (核心)

这步也是核心,我用的是递归解法,不懂的小伙伴需要去了解一下递归的思想(有时间我也写一写递归)。除了第一步,后面的每一步我们都可以考虑最大有四种行走的可能,我们可以写四个方法,分别代表向上、下、左、右移动,行走后是否等于 0 ,也就是是否可以接着行走(可以接着行走,再次调用我们的方法),一直到最后每一个方法都不成立,达到递归返回的条件,这个时候无非两种情况,要么走到死胡同,要么成功了。成功,我们只需要判断这个下标是否为出口点就可以了,然后递返。如果是死胡同,就递返到有交叉出口的地方,也就是能调用两种及以上行走方法的地方,接着走下一条路线。(这里有点绕可以多看看,因为递归有点抽象,不好理解,也不好说)。

所以我画了一个图方便理解。

在这里插入图片描述
我们可以看到从起点开始,代替移动的四个方法只有向下满足,所以这时候只能向下移动,到分叉路口,这个时候移动会根据我们写的移动方法的顺序,接着移动,这里假如是向下的方法优先,就会先向下移动。走蓝色的路线,走到最下面,然后进行判断,走到死胡同了,然后触发我们设置的递归条件,进行递返,一直到交叉口的位置,走红色路线,然后进行判断,在进行递返。
在这里插入图片描述
注意!
我们需要留心的一个小细节,当我们走到一个点的时候,需要改变走过点的值,因为你到下一步,四种可能当中就一定会满足你刚刚走过的点,这样你就又走回去了。

代码

不要看代码多,很多都是每一步的注解,和一些数据的输出,关键代码不多

public class Test {

    public static void main(String[] args) {
        //走迷宫
        String [][]source = {
           {"0", "0", "1", "1", "1"},
           {"1", "0", "1", "1", "0"},
           {"0", "0", "0", "0", "0"},
           {"1", "0", "1", "1", "0"},
           {"0", "0", "1", "1", "0"},
           {"0", "1", "0", "0", "0"},
           {"0", "0", "0", "1", "0"}
        };
        //输出原始数据
        for(int i = 0 ; i < source.length ; i++){
            for(int j = 0 ; j < source[i].length ; j++){
                System.out.print(source[i][j] + " ");
            }
            System.out.println();
        }
        //调用移动的方法 (0,0)为我们设置的起点
        move(0, 0, source);

        System.out.println("--------------");
        for(int i = 0 ; i < source.length ; i++){
            for(int j = 0 ; j < source[i].length ; j++){
                System.out.print(source[i][j] + " ");
            }
            System.out.println();
        }
    }

    public static int move(int a, int b, String [][]source){
        //移动的四个方向
        int ad = a + 1;         //下
        int ax = a - 1;         //上
        int bd = b + 1;         //右
        int bx = b - 1;         //左

        //判断是否满足边界条件
        if(ad < source.length){
            //下  如果能走下一步接着调用移动方法
            if(source[ad][b] == "0"){
                //给走过的路线标记 * 号避免,刚走了下一步,到下一个点又执行向上
                source[a][b] = "*";
                //如果等于 1 表示找到出口 然后一直返回(触发递归的条件)
                if(move(ad, b, source) == 1){
                    source[a][b] = "-";
                    System.out.println(a + "," + b);
                    return 1;
                }
            }
        }
        if(ax >= 0){
            //上
            if(source[ax][b] == "0"){
                source[a][b] = "*";
                if(move(ax, b, source) == 1){
                    source[a][b] = "-";
                    System.out.println(a + "," + b);
                    return 1;
                }
            }
        }
        if(bd < source[a].length){
            //右
            if(source[a][bd] == "0"){
                source[a][b] = "*";
                if(move(a, bd, source) == 1){
                    source[a][b] = "-";
                    System.out.println(a + "," + b);
                    return 1;
                }
            }
        }
        if(bx >= 0){
            //左
            if(source[a][bx] == "0"){
                source[a][b] = "*";
                if( move(a, bx, source) == 1){
                    source[a][b] = "-";
                    System.out.println(a + "," + b);
                    return 1;
                }
            }
        }
            source[a][b] = "*";
            //出口点
            if(a == 5 && b == 4){
                System.out.println("有出口");
                //输出成功的每一个点
                System.out.println(a + "," + b);
                source[a][b] = "-";
                //返回 1 代表成功 0 失败
                return 1;
            }
        return 0;
    }

}
结果

最下面带 - 就是我们的成功的路线,带 * 就是我们走过的但是不通的路线

0 0 1 1 1 
1 0 1 1 0 
0 0 0 0 0 
1 0 1 1 0 
0 0 1 1 0 
0 1 0 0 0 
0 0 0 1 0 
有出口
5,4
5,3
5,2
6,2
6,1
6,0
5,0
4,0
4,1
3,1
2,1
1,1
0,1
0,0
--------------
- - 1 1 1 
1 - 1 1 * 
0 - * * * 
1 - 1 1 * 
- - 1 1 * 
- 1 - - - 
- - - 1 * 

老规矩,这个算法只是作者自己的理解,可能有地方有问题或者bug(毕竟作者也就是一个老一点的菜鸟),如果有问题,可以留言和私信我,看到都会进行修改,让我们共同进步,一起成长 ^ - ^。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值