先出一个迷宫数据文件:
maze.in
6 8
0 1 0 0 0 1 1 0
0 0 0 1 0 1 1 0
0 1 0 1 0 1 1 0
1 0 0 1 0 0 0 1
0 0 1 0 1 1 0 0
1 1 0 0 0 1 1 1
这个文件描述了一个6行8列的迷宫数据,0表示路,1表示墙
接下来要做的就是要使用广度优先算法把这个迷宫给走通,下面简单介绍一下思路,细节部分直接上代码:
1、先设置一个起点为左上角的格子
再设置一个结束点为右下角的格子
2、从起点开始,向四周寻路,向四周寻路时的要点
. 下个点不能越界
. 下个点不能是墙,也就是说,格子里的值不能是1
. 下个点不能是起点
3、维护一个队列,每次发现正确的格子时,都会放到这个队列里面
. 把起点先放在队列里,并从起点开始向四周寻路
. 当前节点寻路完成后会从队列中删除,当前节点四周寻找到的新路都会放在队列里面
. 开启一个新的迷宫数据副本,行列相同,且初始值都为0,每次寻找的路都会在这个副本中打上标签,表示已经被寻找过,并且标签值为步骤数。
4、最后把这个副本的数据打印出来就可以看到寻路的结果了。
直接上代码吧:
main.go
package main
import (
"fmt"
"os"
)
//每次把当前格子加上下面的矩阵 形成四个新的格式
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}
}
type Point struct {
i,j int
}
/**
读取文件中的迷宫,第一行是标文件的行数与列数;后面的矩阵数据 0表示是路,1表示是墙
*/
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)
fmt.Printf("%d %d\n\n",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
}
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 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]
if(cur == end){
break
}
Q = Q[1:]
for i:=0;i< len(dirs); i++{
nextPoint := cur.add(dirs[i])
if nextPoint == end{
fmt.Println()
}
//下个点不是0则不能走
//下个点走过了也不能走
//下个点为起点也不能走
//判断nextPoint是否越界或撞墙,如果是则放弃nextPoint
val,ok := nextPoint.at(maze)
if val == 1 || !ok{
continue
}
//判断nextPoint是否曾被走过
val,ok = nextPoint.at(steps)
if val != 0 {
continue
}
//判断是否回到原点
if nextPoint == start {
continue
}
//标记steps里的网格被第几步走过
curSteps,_ := cur.at(steps)
steps[nextPoint.i][nextPoint.j] = curSteps+1
if curSteps == 12{
fmt.Println()
}
//向队列中放入新的可走路径
Q = append(Q, nextPoint)
}
}
return steps
}
func main() {
maze :=readMaze("arithmetic/maze/maze.in")
//for _,item := range maze{
// fmt.Printf("%v\n",item)
//}
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()
}
}
运行结果:
0 0 4 5 6 0 0 0
1 2 3 0 7 0 0 0
2 0 4 0 8 0 0 0
0 6 5 0 9 10 11 0
8 7 0 0 0 0 12 13
0 0 0 0 0 0 0 0
可以看出最短8步最长13步可能把迷宫给走通