day21 Go 实现的深度优先搜索实现迷宫算法

 

# 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
}

// 反转slice
func reverse(lst []point) []point {
	newList := []point{}
	for index, _ := range lst {
		n := len(lst) - index - 1
		newList = append(newList, lst[n])
	}
	return newList
}

func isExist(lst []point, n point) error {
	for _, ex := range lst {
		if ex == n {
			return errors.New(" is exist!")
		}
	}
	return nil
}

// 移动步骤顺序: 上、左、下、右
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) []point {

	Q := []point{start}
	history := []point{start}
	search_path := []point{}

	for {
		// 此处的flag用于判断当前的坐标的下几个步骤是否都是死路,如果有一个出口就标记为true,后面需要判断死路使用
		flag := false

		now := Q[len(Q)-1]
		search_path = append(search_path, now)

		// 找到出口
		if now == end {
			break
		}

		for _, d := range direction {
			next := now.move(d)

			// 判断下个点在前面没有探测过, 避免重复探测
			if isExist(history, next) == nil {
				// 判断移动没有越界,而且没有撞墙的话将下个点加入到队列中
				val, err := next.at(maze)
				if err == nil && val != 1 {
					Q = append(Q, next)
					history = append(history, next)
					//fmt.Printf("now:%d, moveTo:%d, next:%d \n", now, d, next)
					flag = true
					continue
				}

			} else {
				//fmt.Println("3--> history is exist ", next)
			}
		}

		// 判断当前坐标移动的下一步都是是死路的时候删除队列中最后一个元素
		if flag == false && isExist(history, now) != nil {
			//fmt.Println("dead way", now)
			Q = Q[:len(Q)-1]
			search_path = search_path[:len(search_path)-1]
		}

	}

	return search_path
}

func main() {

	maze := readMazeFile("/Users/fanghongbo/CloudStation/go/goDemo/src/chapter09/maze.txt")
/* maze.txt的内容如下:
6 5
0 1 0 0 0
0 0 0 1 0
0 1 0 1 0
1 1 1 0 0
0 1 0 0 1
0 1 0 0 0
*/
	fmt.Printf("maze: \n\n")
	for i := range maze {
		for j := range maze[i] {
			fmt.Printf("%3d", maze[i][j])
		}
		fmt.Println()
	}
	fmt.Println()

	path := walk(maze, point{0, 0}, point{len(maze) - 1, len(maze[0]) - 1})
	fmt.Printf("最终路径为:%d\n",path)
}

  

 

posted @ 2018-11-21 15:52  秋风亦冷  阅读(636)  评论(0编辑  收藏  举报