算法_迷宫寻路算法_广度优先

先出一个迷宫数据文件:
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步可能把迷宫给走通

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值