golang學習筆記——迷宮的廣度優先搜尋

kuc火發表於2020-09-25

迷宮演算法

package main

import (
	"fmt"
	"os"
)

const (
	mazePath = "/home/udi/Udi_work_space/Udi_ws_go/muke/12/1&2/maze.txt"
)

func readMaze(path string) [][]int {
	// var res [][]int
	open, errOpen := os.Open(path)
	if errOpen != nil {
		panic(errOpen)
	}

	var row, col int
	fmt.Fscanf(open, "%d %d", &row, &col)
	maze := make([][]int, row)
	for i := range maze {
		maze[i] = make([]int, col)
		for j := range maze[i] {
			fmt.Fscanf(open, "%d", &maze[i][j])
		}
	}

	return maze
}

type point struct {
	i, j int
}

var (
	dirs = [4]point{
		{-1, 0}, //上
		{0, -1}, //left
		{1, 0},  //down
		{0, 1},  //right
	}
)

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
}

func walkMaze(maze [][]int, start, end point) ([][]int, []point) {
	//建立一個與maze一模一樣但是裡面value全為0的二元陣列
	steps := make([][]int, len(maze))
	res := []point{}
	for i := range steps {
		steps[i] = make([]int, len(maze[i]))
	}

	Q := []point{start}

	for len(Q) > 0 {
		cur := Q[0]
		Q = Q[1:]

		if cur == end {
			break
		}

		for _, dir := range dirs {
			next := cur.add(dir)
			//maze at next is 0
			//and steps at next is 0
			//and next != start
			value, ok := next.at(maze)
			if !ok || value == 1 {
				continue
			}
			value, ok = next.at(steps)
			if !ok || value != 0 {
				continue
			}
			if next == start {
				continue
			}
			curStep, _ := cur.at(steps)
			steps[next.i][next.j] = curStep + 1
			res = append(res, point{next.i + 1, next.j + 1})
			Q = append(Q, next)
		}
	}

	return steps, res
}

func main() {
	res := readMaze(mazePath)
	// for _, row := range res {
	// 	for _, val := range row {
	// 		fmt.Printf("%d ", val)
	// 	}
	// 	fmt.Println()
	// }

	step, resPoint := walkMaze(res, point{0, 0}, point{len(res) - 1, len(res[0]) - 1})

	for _, row := range step {
		for _, val := range row {
			fmt.Printf("%3d", val)
		}
		fmt.Println()
	}
	fmt.Println(resPoint)
}

  • 為爬蟲實戰專案做好準備
  • 應用廣泛,綜合性強
  • 面試常見的問題
  • 用迴圈來建立一個二維slice
  • 使用slice來實現佇列
  • 用Fscanf讀取檔案
  • 對point的抽象

相關文章