java如何實現迷宮演算法
回溯法是一種不斷試探且及時糾正錯誤的搜尋方法,下面的求解過程採用回溯法。從入口出發,按某一方向向前探索,若能走通(未走過的),即某處可以到達,則到達一個新點,否則試探下一個方向;若所有的方向均沒有通路,則沿原路返回前一點,換下一個方向繼續試探,直到所有可能的通路都搜尋到,或找到一條通路,或無路可走又返回到入口點。這裡可以用一個棧來實現,每走一步,將該位置壓入棧中,若該點無路可走,則出棧返回上一位置。
需要解決的四個問題:
(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個方向可以試探。其增量陣列可以用一個8*2的二維陣列move表述,表示對當前點而言,它周圍8個點的行和列的座標偏移量.具體值如下:
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)棧中存放元素的設計
棧中所存放的元素應該包含所到達的每點的座標以及從該點沿哪個方向向下走的,可用一個類表示:
class Step{
int x,y,d;
public Step(int x,int y,int d) {
this.x = x;//橫座標
this.y = y;//縱座標
this.d = d;//方向
}
}
(4)防止重複到達某點而發生死迴圈
使maze[i][j]置為-1,以便區別為達到的點,同樣也可以防止走重複點的作用。
原始碼如下:
package com.test;
import java.util.Stack;
class Step{
int x,y,d;
public Step(int x,int y,int d) {
this.x = x;//橫座標
this.y = y;//縱座標
this.d = d;//方向
}
}
public class MazeTest {
public static void main(String[] args) {
// 迷宮定義
int[][] maze = {{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}};
int[][] move = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
Stack s = new Stack();
Stack s1 = new Stack();
int a = path(maze, move, s);
while(!s.isEmpty()){
Step step = s.pop();
System.out.println(step.x+”:”+step.y);
}
}
public static int path(int[][] maze,int[][] move,Stack s){
Step temp = new Step(1,1,-1); //起點
s.push(temp);
while(!s.isEmpty()){
temp = s.pop();
int x = temp.x;
int y = temp.y;
int d = temp.d+1;
while(d<8){
int i = x + move[d][0];
int j = y + move[d][1];
if(maze[i][j] == 0){ //該點可達
temp = new Step(i,j,d); //到達新點
s.push(temp);
x = i;
y = j;
maze[x][y] = -1; //到達新點,標誌已經到達
if(x == 6 && y == 8){
return 1; //到達出口,迷宮有路,返回1
}else{
d = 0; //重新初始化方向
}
}else{
d++; //改變方向
}
}
}
return 0;
}
}