沿着所有方向進行探測,有路徑則走,沒有路徑則從棧中回退。
回溯法是一種不斷試探且及時糾正錯誤的搜索方法,下面的求解過程采用回溯法。從入口出發,按某一方向向前探索,若能走通(未走過的),即某處可以到達,則到達一個新點,否則試探下一個方向;若所有的方向均沒有通路,則沿原路返回前一點,換下一個方向繼續試探,直到所有可能的通路都搜索到,或找到一條通路,或無路可走又返回到入口點。這里可以用一個棧來實現,每走一步,將該位置壓入棧中,若該點無路可走,則出棧返回上一位置。
需要解決的四個問題:
(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 1
1 1
1 0
1 -1
0 -1
-1 -1
-1 0
-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; } }
代碼2:
import java.util.*; class Position{ public Position(){ } public Position(int row, int col){ this.col = col; this.row = row; } public String toString(){ return "(" + row + " ," + col + ")"; } int row; int col; } class Maze{ public Maze(){ maze = new int[15][15]; stack = new Stack<Position>(); p = new boolean[15][15]; } /* * 構造迷宮 */ public void init(){ Scanner scanner = new Scanner(System.in); System.out.println("請輸入迷宮的行數"); row = scanner.nextInt(); System.out.println("請輸入迷宮的列數"); col = scanner.nextInt(); System.out.println("請輸入" + row + "行" + col + "列的迷宮"); int temp = 0; for(int i = 0; i < row; ++i) { for(int j = 0; j < col; ++j) { temp = scanner.nextInt(); maze[i][j] = temp; p[i][j] = false; } } } /* * 回溯迷宮,查看是否有出路 */ public void findPath(){ // 給原始迷宮的周圍家一圈圍牆 int temp[][] = new int[row + 2][col + 2]; for(int i = 0; i < row + 2; ++i) { for(int j = 0; j < col + 2; ++j) { temp[0][j] = 1; temp[row + 1][j] = 1; temp[i][0] = temp[i][col + 1] = 1; } } // 將原始迷宮復制到新的迷宮中 for(int i = 0; i < row; ++i) { for(int j = 0; j < col; ++j) { temp[i + 1][j + 1] = maze[i][j]; } } // 從左上角開始按照順時針開始查詢 int i = 1; int j = 1; p[i][j] = true; stack.push(new Position(i, j)); while (!stack.empty() && (!(i == (row) && (j == col)))) { if ((temp[i][j + 1] == 0) && (p[i][j + 1] == false)) { p[i][j + 1] = true; stack.push(new Position(i, j + 1)); j++; } else if ((temp[i + 1][j] == 0) && (p[i + 1][j] == false)) { p[i + 1][j] = true; stack.push(new Position(i + 1, j)); i++; } else if ((temp[i][j - 1] == 0) && (p[i][j - 1] == false)) { p[i][j - 1] = true; stack.push(new Position(i, j - 1)); j--; } else if ((temp[i - 1][j] == 0) && (p[i - 1][j] == false)) { p[i - 1][j] = true; stack.push(new Position(i - 1, j)); i--; } else { stack.pop(); if(stack.empty()){ break; } i = stack.peek().row; j = stack.peek().col; } } Stack<Position> newPos = new Stack<Position>(); if (stack.empty()) { System.out.println("沒有路徑"); } else { System.out.println("有路徑"); System.out.println("路徑如下:"); while (!stack.empty()) { Position pos = new Position(); pos = stack.pop(); newPos.push(pos); } } /* * 圖形化輸出路徑 * */ String resault[][]=new String[row+1][col+1]; for(int k=0;k<row;++k){ for(int t=0;t<col;++t){ resault[k][t]=(maze[k][t])+""; } } while (!newPos.empty()) { Position p1=newPos.pop(); resault[p1.row-1][p1.col-1]="#"; } for(int k=0;k<row;++k){ for(int t=0;t<col;++t){ System.out.print(resault[k][t]+"\t"); } System.out.println(); } } int maze[][]; private int row = 9; private int col = 8; Stack<Position> stack; boolean p[][] = null; } class hello{ public static void main(String[] args){ Maze demo = new Maze(); demo.init(); demo.findPath(); } }