java栈 迷宫_利用栈实现迷宫的求解

本文介绍了如何使用Java栈结合回溯法解决迷宫问题。通过创建一个表示迷宫的数据结构,利用栈存储路径,并设计试探方向,以避免死循环。文章详细阐述了解决方案的四个关键步骤,并提供了相应的Java代码示例。
摘要由CSDN通过智能技术生成

问题描述:这时实验心理学中的一个典型的问题,心理学家吧一只老鼠从一个无顶的大盒子的入口处赶进迷宫。迷宫设置很多隔壁,对前进方向形成了许多障碍,心理学家在迷宫的唯一出口处放置了一块奶酪,吸引老鼠仔迷宫中寻找通路以到达出口。

求解思想:回溯法是一种不断试探且及时纠正错误的搜索方法,下面的求解过程采用回溯法。从入口出发,按某一方向向前探索,若能走通(未走过的),即某处可以到达,则到达一个新点,否则试探下一个方向;若所有的方向均没有通路,则沿原路返回前一点,换下一个方向继续试探,直到所有可能的通路都搜索到,或找到一条通路,或无路可走又返回到入口点。这里可以用一个栈来实现,每走一步,将该位置压入栈中,若该点无路可走,则出栈返回上一位置。

需要解决的四个问题:

(1)表示迷宫的数据结构

设迷宫为m行n列,利用数组maze[m][n]来表示一个迷宫,maze[i][j]=0或1,其中0表示通路,1表示不通。迷宫该数组四边都为1,代表迷宫四周都是墙。这样就可以保证每个点都有8个方向可以试探。

入口为(1,1),出口为(6,8)

1,1,1,1,1,1,1,1,1,1

1,0,1,1,1,0,1,1,1,1

1,1,0,1,0,1,1,1,1,1

1,0,1,0,0,0,0,0,1,1

1,0,1,1,1,0,1,1,1,1

1,1,0,0,1,1,0,0,0,1

1,0,1,1,0,0,1,1,0,1

1,1,1,1,1,1,1,1,1,1

(2)试探方向

迷宫中间每个点都有8个方向可以试探。其增量数组可以用一个1*2的二维数组move表述,具体值如下:

x  y

0  0  1

1    1     1

2    1     0

3    1     -1

4    0     -1

5    -1    -1

6    -1    0

7    -1    1

在move数组中,x表示横坐标的增量,y表示纵坐标的增量。

(3)栈中存放元素的设计

栈中所存放的元素应该包含所到达的每点的坐标以及从该点沿哪个方向向下走的。可以用一个类表示:

1 classStep{2 intx,y,d;3 public Step(int x,int y,intd) {4 this.x = x;//横坐标

5 this.y = y;//纵坐标

6 this.d = d;//方向

7 }8 }

(4)防止重复到达某点而发生死循环

可以用两种方法来实现,第一种就是另外设置一个标志数组mark[m][n],它的所有元素初始都为0,一旦到达某点,则设置该点的标志位1,下次试探的时候就不再走这点了。第二种就是当到达某点的时候,使maze[i][j]置为-1,以便区别为达到的点,同样也可以防止走重复点的作用。

具体代码如下:

1 packagecom.stack;2

3 importjava.util.Stack;4

5 /**

6 * 用栈来实现迷宫的求解7 *@author刘玲8 *9 */

10

11 classStep{12 intx,y,d;13 public Step(int x,int y,intd) {14 this.x = x;//横坐标

15 this.y = y;//纵坐标

16 this.d = d;//方向

17 }18 }19

20 public classMazeTest {21

22 public static voidmain(String[] args) {23 //迷宫定义

24 int[][] maze = {{1,1,1,1,1,1,1,1,1,1},25 {1,0,1,1,1,0,1,1,1,1},26 {1,1,0,1,0,1,1,1,1,1},27 {1,0,1,0,0,0,0,0,1,1},28 {1,0,1,1,1,0,1,1,1,1},29 {1,1,0,0,1,1,0,0,0,1},30 {1,0,1,1,0,0,1,1,0,1},31 {1,1,1,1,1,1,1,1,1,1}};32 int[][] move = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};33 Stack s = new Stack();34 Stack s1 = new Stack();35 int a =path(maze, move, s);36 while(!s.isEmpty()){37 Step step =s.pop();38 System.out.println(step.x+":"+step.y);39 }40 }41 public static int path(int[][] maze,int[][] move,Stacks){42 Step temp = new Step(1,1,-1); //起点

43 s.push(temp);44 while(!s.isEmpty()){45 temp =s.pop();46 int x =temp.x;47 int y =temp.y;48 int d = temp.d+1;49 while(d<8){50 int i = x + move[d][0];51 int j = y + move[d][1];52 if(maze[i][j] == 0){ //该点可达

53 temp = new Step(i,j,d); //到达新点

54 s.push(temp);55 x =i;56 y =j;57 maze[x][y] = -1; //到达新点,标志已经到达

58 if(x == 6 && y == 8){59 return 1; //到达出口,迷宫有路,返回1

60 }else{61 d = 0; //重新初始化方向

62 }63 }else{64 d++; //改变方向

65 }66 }67 }68 return 0;69 }70

71 }

输出结果如下:

6:8

5:8

5:7

5:6

4:5

3:5

3:4

3:3

2:2

由于栈是后进先出的,所以结果应该从下面看起(2,2)->(3,3)->(3,4)->(3,5)->(4,5)->(5,6)->(5,7)->(5,8)->(6,8)

有运行结果可以看出来,栈中所存储的就是迷宫的一条通路。

上面那个代码有一点点小问题,非常感谢问题的提出者,修改如下:

1 packagecom.stack;2

3 importjava.util.Stack;4

5 /**

6 * 用栈来实现迷宫的求解7 *@author刘玲8 *9 */

10

11 classStep{12 intx,y,d;13 public Step(int x,int y,intd) {14 this.x = x;//横坐标

15 this.y = y;//纵坐标

16 this.d = d;//方向

17 }18 }19

20 public classMazeTest {21

22 public static voidmain(String[] args) {23 //迷宫定义

24 int[][] maze = {{1,1,1,1,1,1,1,1,1,1},25 {1,0,1,1,1,0,1,1,1,1},26 {1,1,0,1,0,1,1,1,1,1},27 {1,0,1,0,0,0,0,0,1,1},28 {1,0,1,1,1,0,1,1,1,1},29 {1,1,0,0,1,1,0,0,0,1},30 {1,0,1,1,0,0,1,1,0,1},31 {1,1,1,1,1,1,1,1,1,1}};32 int[][] move = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};33 Stack s = new Stack();34 int a =path(maze, move, s);35 while(!s.isEmpty()){36 Step step =s.pop();37 System.out.println(step.x+":"+step.y);38 }39 }40 public static int path(int[][] maze,int[][] move,Stacks){41 Step temp = new Step(1,1,-1); //起点

42 s.push(temp);43 while(!s.isEmpty()){44 //temp = s.pop(); 这样写是有问题的,不能将出栈的元素作为当前位置,应该将栈顶元素作为当前位置

45 s.pop(); //如果路走不通就出栈

46 if(!s.isEmpty()){47 temp = s.peek(); //将栈顶元素设置为当前位置

48 }49 int x =temp.x;50 int y =temp.y;51 int d = temp.d+1;52 while(d<8){53 int i = x + move[d][0];54 int j = y + move[d][1];55 if(maze[i][j] == 0){ //该点可达

56 temp = new Step(i,j,d); //到达新点

57 s.push(temp);58 x =i;59 y =j;60 maze[x][y] = -1; //到达新点,标志已经到达

61 if(x == 6 && y == 1){62 return 1; //到达出口,迷宫有路,返回1

63 }else{64 d = 0; //重新初始化方向

65 }66 }else{67 d++; //改变方向

68 }69 }70 }71 return 0;72 }73

74 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值