1. 程式人生 > >Go 迷宮算法

Go 迷宮算法

idt 一維數組 沒有 通過 alt name walk 根據 col

首先讀取一個迷宮文件maze.in (第一行是文件的行列 下面是文件內容:1表示墻 0表示此路可走)

技術分享圖片技術分享圖片

如何讀取?

//讀取一個二維數組 
func readMaze(filename string) [][]int {
    // 先打開文件 默認是已經存在這個文件 故沒有做其他出錯處理
    file, err := os.Open(filename)  
    if err != nil {
        panic(err)
    }
    //需要先將行、列讀出來 利用Fscanf讀取
    var row, col int
    fmt.Fscanf(file, 
"%d %d", &row, &col) //創建二維slice 註意:這裏是傳入參數行row 因為二維數組其實就是:有row這麽多一維數組構成 這裏是使用切片 maze := make([][]int, row) for i := range maze { maze[i] = make([]int, col) //利用make創建 for j := range maze[i] { fmt.Fscanf(file, "%d", &maze[i][j]) } }
return maze } func main() { maze := readMaze("mazepractice/maze.in") for _,row := range maze { for _,val := range row { fmt.Printf("%3d",val) } fmt.Println() } }

迷宮算法解讀

package main

import (
    "fmt"
    "os"
)

func readMaze(filename 
string) [][]int { file, err := os.Open(filename) 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 } // 定義點的結構體 因為這裏是數組 最好不要用x,y定義(以免自己與坐標混淆) type point struct { i, j int } // 定義4個方向分別是:上 左 下 右 方向 var dirs = [4]point{ {-1, 0}, {0, -1}, {1, 0}, {0, 1}} // 走迷宮需要從上左下右方向去走,因此坐標會相應的變化 註:這裏是利用返回一個新的point 而不是利用指針(當然,指針也可以) func (p point) add(r point) point { return point{p.i + r.i, p.j + r.j} } //判斷走的點是不是合理的 有沒越界 返回值是點和一個狀態值 func (p point) at(grid [][]int) (int, bool) { if p.i < 0 || p.i >= len(grid) { return 0, false } if p.j < 0 || p.j >= len(grid[p.i]) { return 0, false } return grid[p.i][p.j], true } // 走迷宮的關鍵算法 通過傳入3個參數:二維切片,開始點,結束點 返回的是:一個二維切片 func walk(maze [][]int, start, end point) [][]int { // 這裏其實是創建一個走過路線的steps 根據我們讀取的文件maze.in規格大小來創建 steps := make([][]int, len(maze)) for i := range steps { steps[i] = make([]int, len(maze[i])) } // 創建一個隊列 開始點是(0,0) Q := []point{start} // 隊列不空 for len(Q) > 0 { cur := Q[0] //cur代表隊列開始點(0,0) Q = Q[1:] //去掉隊列第一個點 // 發現終點 退出 if cur == end { break } // 沒有走到的請看 for _, dir := range dirs { // 通過上 左 下 右 走這些路 next := cur.add(dir) // 判斷走的路線是不是可以走:0 可以走 1 不可以走 當然越界也是不行的 val, ok := next.at(maze) if !ok || val == 1 { continue } // 判斷這些點有沒有走過:就是不要走回頭路 val, ok = next.at(steps) if !ok || val != 0 { continue } // 不是0 可能回到起點 不行的 if next == start { continue } // 當前的步驟數 curSteps, _ := cur.at(steps) steps[next.i][next.j] = curSteps + 1 // 把這個放在隊列的後面 Q = append(Q, next) } } return steps } func main() { maze := readMaze("mazepractice/maze.in") steps := walk(maze, point{0, 0}, point{len(maze) - 1, len(maze[0]) - 1}) // 打印實際走的這個數組 for _, row := range steps { for _, val := range row { fmt.Printf("%3d", val) } fmt.Println() } lessStep := steps[len(maze)-1][len(maze[0])-1] fmt.Printf("這個迷宮最少需要%d步走完",lessStep) // TODO: construct path from steps }

左邊是讀取的文件,右邊是輸出結果:

技術分享圖片技術分享圖片

左邊是讀取的文件,右邊是輸出結果:

技術分享圖片技術分享圖片

Go 迷宮算法