maze_test.go
package algorithm
import (
"fmt"
"os"
"testing"
)
type point struct {
i, j int
}
var dirs = [4]point{
{-1, 0},
{0, -1},
{1, 0},
{0, 1},
}
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
}
// 行走
// 维护一份自己的地图 和 迷宫 大小 是一样的 初始化 为0 然后 每一次走到下一个点的是否在 索引为上一个点 加 1
func walk(maze [][]int, start, end point) [][]int {
steps := make([][]int, len(maze))
//复制跟迷宫列数一样大小的列数
for i := range steps {
steps[i] = make([]int, len(maze[0]))
}
//初始化队列 数组 加入起始坐标
Q := []point{start}
//如果队列里面还有可以走的 点就去走
for len(Q) > 0 {
//总是从 数组的头取 实现先进先出的队列
cur := Q[0]
//上面去除的坐标点 去除
Q = Q[1:]
//上下左右走 如果走的同把那个点加入到队列
for _, dir := range dirs {
//计算走后的坐标点
next := cur.add(dir)
//判断是否超界 判断是否 是 1 1的话是墙 不能走
val, ok := next.at(maze)
if !ok || val == 1 {
continue
}
//看看你的地图 是否这个点 在你的地图里 已近走过了
val, ok = next.at(steps)
//如果这个点 已经走过了 也去除
if !ok || val != 0 {
continue
}
//如果这个点 是原点 也不能再走 原点也是走过的点 特殊的是原点是0 上面 判断条件是 排除0 的点 所以需要单独判断
if next == start {
continue
}
//出发点的坐标
curwSteps, _ := cur.at(steps)
//在你的地图上 跟新这个找到的点 索引为上一个点+1
steps[next.i][next.j] = curwSteps + 1
//将这个点加入队列
Q = append(Q, next)
}
}
return steps
}
func TestMaze(t *testing.T) {
maze := readMaze("./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()
}
}
func readMaze(fileName string) [][]int {
file, err := os.Open(fileName)
if err != nil {
panic(err)
}
defer file.Close()
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
}
maze.in
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