零基础学Java——递归应用:迷宫问题 保姆级思路分析和步骤详解(附上完整源代码)

文章目录


前言

本篇文章是韩顺平老师课程P221(第7章:面向对象编程)中有关方法递归调用应用实例1:老鼠出迷宫问题的具体分析。

本篇文章会详细分析每一步解决思路,对应的每步代码构建,最后会放上完整源代码供大家参考,可以作为老韩学Java课程系列笔记的补充,也可以作为想要单独弄清楚迷宫问题的专题文章,希望能够帮助到的大家。

关于方法递归调用的前置知识,欢迎查看我的从零开始学Java(超详细韩顺平老师笔记梳理)06——面向对象编程基础(上):类与对象、成员方法、传参机制、对象克隆、递归(斐波那契、迷宫、汉诺塔、八皇后)笔记。


老鼠迷宫问题:
在这里插入图片描述

思路分析:

  1. 首先我们需要把迷宫这个地图和障碍表示出来(数组是从0开始的,不是从1 开始)

    • 这里我们可以使用一个二维数组画出格子图,即8行七列
      在这里插入图片描述

    • 1表示地图中的障碍,用0表示无障碍可以正常通行

    • 通过观察可以知道,第一行和最后一行、第一列和最后一列(红色)全是障碍物,所以可以先通过一个for循环来将这四部分写为1(有障碍)

      • 先将第一行和最后一行设置为1
        在这里插入图片描述
        我们将此时的地图打印一下,检测是否符合预期效果:
        在这里插入图片描述
      • 把第一列和最后一列也设置为1
        在这里插入图片描述打印一下地图看看:
        在这里插入图片描述
    • 除去边框的部分,我们发现在图中坐标为[3][1]、[3][2]的地方也是障碍,这两个障碍我们单独设置一下
      在这里插入图片描述
      在这里插入图片描述
      打印看一下:
      在这里插入图片描述
      至此地图和障碍部分我们已经实现了。

  2. 接下来要实现老鼠找路的过程
    在这里插入图片描述

    在这里插入图片描述

    • 我们先把找到终点 (返回true) 和**有障碍、已经走过(返回false)**的情况给写出来
      在这里插入图片描述

    • 而找路的核心代码为:当map[i][j] == 0时,即这个地方没有障碍,之前也没有走过

      • 首先我们往下走一步,再递归调用找路方法,如果发现往下走一步,map[i][j] 还是= 0,那么就说明往下走一步是行得通的,返回true
        在这里插入图片描述
      • 按照我们的走路策略(下->右->上->左),按照往下走的相同思路实现完4条路的递归实现:
        在这里插入图片描述
      • 但是如果这四步都没有走通,那说明我们的前提条件map[i][j] == 2(这条路能走通)就不成立,我们直接把这个条件map[i][j]设为3(走过但走不通)
        在这里插入图片描述 - 至此,我们这个findWay方法就已经写完了,我们需要在main方法中调用该方法 , 把老鼠的初始坐标设置为map[1][1],再次打印出地图,看看路径。
        在这里插入图片描述
        在这里插入图片描述

至此,我们的迷宫问题就已经实现了,大家可以自己更换走路策略,然后再次测试,会得到很多种不同的路径。

完整代码如下:

public class Migong{
	public static void main(String[] args) {

		//1. 先创建迷宫,用二维数组表示 即int[][] map = new int[8][7]
		//2. 我们先规定map数组的元素值,0表示没有障碍,1表示有障碍
		int[][] map = new int[8][7];
		
		//第一行和最后一行全是障碍物,全部设置为1
		for(int i = 0; i < 7; i++){

			//第1行的1、2、3、4...7列格子(即第一行全部)全部设置为1
			map[0][i] = 1; 
			
			//第8行的1、2、3、4...7列格子(即最后一行全部)全部设置为1
			map[7][i] = 1;

		}

		//第一列和最后一列全是障碍物,全部设置为1
		for(int i = 0; i < 8; i++) {

			//第1列的1、2、3、4...8行格子(即第一行全部)全部设置为1
			map[i][0] = 1; 
			
			//第7行的1、2、3、4...8行格子(即最后一行全部)全部设置为1
			map[i][6] = 1;
		}

		map[3][1] = 1;
		map[3][2] = 1;
		
		//输出当前地图,用于每一步的测试
		System.out.println("======当前地图为======");

		for(int i =0; i < map.length; i++) {
			for(int j = 0; j < map[i].length; j++) {
				System.out.print(map[i][j] + " "); //输出一行
			}
			System.out.println();
		}

		//使用findWay给老鼠找路
		T t1 = new T();
		t1.findWay(map, 1, 1);

		System.out.println("\n======找路后的情况如下======");

		for(int i =0; i < map.length; i++) {
			for(int j = 0; j < map[i].length; j++) {
				System.out.print(map[i][j] + " "); //输出一行
			}
			System.out.println();
		}

	}
}

class T {
	//使用递归回溯的思想来解决老鼠出迷宫

	/*
	  1. findWay方法就是专门用来找迷宫的路径
	  2. 如果找到,就返回true,否则返回false
	  3. map 就是二维数组,即表示迷宫
	  4. 老鼠的初始位置为map[1][1]
	  5. 因为是递归找路,我们规定map数组的各个值的含义:
	     0--无障碍
	     1--障碍
	     2--这个路能走通,我们已经走过了测试过了(插个棋子)
	     3--走过,但是走不通
      6. 当map[6][5]=2时,说明找到通路了,否则就继续找
      
      7. 先确定老鼠找路的策略(这部分可以自己定义)
      	 先往下走,下走不通了就往右走,右走不通就往上走,上走不通就往左走
      	 下->右->上->左

	*/   

	public boolean findWay(int[][] map, int i, int j) {
		
		if(map[6][5] == 2) { //说明已经找到
			return true;
		} else {
			if(map[i][j] == 0) { //说明这个地方没有障碍可以走,但是我们还没有走过
				//我们假定可以走通
				map[i][j] = 2;

				//使用找路策略,来确定该位置是否真的可以走通
				//下->右->上->左
				if(findWay(map, i + 1, j)){ //i+1就是表示往下走一步
					//这里递归调用方法,如果往下走一步还是map[i][j] == 0
					//那么这条路可以走通,返回true
					return true;
				} else if(findWay(map, i, j + 1)) {//j+1就是表示往右走一步
					//如果往下走并没有走通,就往右走
					return true;
				} else if(findWay(map, i - 1, j)) {//i-1就是表示往上走一步
					//如果往右走并没有走通,就往上走
					return true;
				} else if(findWay(map, i, j - 1)) {//j-1就是表示往左走一步
					//如果往上走并没有走通,就往左走
					return true;
				} else {

					//但是如果这四步都没有走通
					//那说明我们的前提条件map[i][j] == 2(这条路能走通)就不成立
					//我们直接把这个条件map[i][j]设为3(走过但走不通)
					map[i][j] =3;
					return false;
				}

			} else { //map[i][j] = 1, 2, 3
				//1表示有障碍
				//2表示已经测试过能走通,走过了
				//3表示走过,走不通
				return false;
			}
		}

	}
}

总结

本篇文章是韩顺平老师课程P221(第7章:面向对象编程)中有关方法递归调用应用实例1:老鼠出迷宫问题的具体分析。

本篇文章会详细分析每一步解决思路,对应的每步代码构建,最后会放上完整源代码供大家参考,可以作为老韩学Java课程系列笔记的补充,也可以作为想要单独弄清楚迷宫问题的专题文章,希望能够帮助到的大家。

关于方法递归调用的前置知识,欢迎查看我的从零开始学Java(超详细韩顺平老师笔记梳理)06——面向对象编程基础(上):类与对象、成员方法、传参机制、对象克隆、递归(斐波那契、迷宫、汉诺塔、八皇后)笔记。

  • 25
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值