Go實現的廣度優先搜尋實現迷宮演算法
阿新 • • 發佈:2018-11-20
# 使用go實現的廣度優先搜尋實現迷宮演算法
package main import ( "errors" "fmt" "os" ) // 讀取檔案中的資料,使用迴圈生成迷宮圖 func readMazeFile(filename string) [][]int { file, err := os.Open(filename) defer file.Close() if err != nil { panic(err) } var row, col int fmt.Fscanf(file, "%d %d", &row, &col) maze := make([][]int, row) for i := range maze { maze[i] = make([]int, col) for j := range maze[i] { fmt.Fscanf(file, "%d", &maze[i][j]) } } return maze } type point struct { i, j int } // 移動步驟順序: 上、左、下、右 var direction = [4]point{ {-1, 0}, {0, -1}, {1, 0}, {0, 1}} // 執行上左下右移動操作 func (p point) move(r point) point { return point{p.i + r.i, p.j + r.j} } // 判斷移動之後的位置是否有越界或者撞牆 func (p point) at(grid [][]int) (int, error) { if p.i < 0 || p.i >= len(grid) { return 0, errors.New("raw out of range") } if p.j < 0 || p.j >= len(grid[0]) { return 0, errors.New("col out of range") } return grid[p.i][p.j], nil } func walk(maze [][]int, start, end point) [][]int { // 建立一個全0的二維陣列,填行走的步驟 steps := make([][]int, len(maze)) for i := range steps { steps[i] = make([]int, len(maze[i])) } Q := []point{start} for len(Q) > 0 { index := Q[0] // 每次取佇列中的第一個元素進行上左下右移動 // 發現終點,直接退出 if index == end { break } Q = Q[1:] for _, d := range direction { next := index.move(d) val, err := next.at(maze) // 遇到牆或者越界,跳過本次迴圈 if err != nil || val == 1 { continue } // 新的二維陣列中移動的下一個點如果值不是0的話,說明已經走過這個點,直接跳過 val, err = next.at(steps) if err != nil || val != 0 { continue } // 回到原點,也要跳過 if next == start { continue } // steps二維陣列初始值都是0,每走一步,原來的地方填上行走的步數上加一 stepsNum, _ := index.at(steps) steps[next.i][next.j] = stepsNum + 1 // 每走一步,先加入到佇列中 Q = append(Q, next) } } return steps } func main() { maze := readMazeFile("/Users/fanghongbo/CloudStation/go/goDemo/src/chapter09/maze.txt") fmt.Println("source maze: ") for i := range maze { for j := range maze[i] { fmt.Printf("%3d", maze[i][j]) } fmt.Println() } steps := walk(maze, point{0, 0}, point{len(maze) - 1, len(maze[0]) - 1}) fmt.Println("\nnew steps: ") for i := range steps { for j := range steps[i] { fmt.Printf("%3d", steps[i][j]) } fmt.Println() } fmt.Println("") i := len(maze) - 1 j := len(maze[0]) - 1 fmt.Printf("走出迷宮總共移動的%d步\n",steps[i][j]) // 計算最優路徑 last := steps[i][j] lookupPath := []point{point{i,j}} for last > 0 { last = last - 1 index := lookupPath[len(lookupPath)-1] for _, d := range direction { next := index.move(d) val, _ := next.at(steps) if val == last { lookupPath = append(lookupPath,next) //fmt.Println(last,index,next) break } } } // 反轉lookupPath newPath := []point{} for index,_ := range lookupPath { n := len(lookupPath) - index - 1 newPath = append(newPath, lookupPath[n]) } fmt.Printf("最優路徑:%d", newPath) }