12.2 迷宫代码实现
一、实现
用循环创建二维slice
使用slice来实现队列
用Fscanf读取文件
对Point的抽象
二、代码
package main
import (
"fmt"
"os"
)
// 读取文件
func readMaze(filename string) [][]int {
// 读取文件
file, err := os.Open(filename)
if err != nil {
fmt.Println(err)
panic("文件读取失败")
}
// 读取内容
var row, col int
fmt.Fscanf(file, "%d %d", &row, &col)
maze := make([][]int, row) // 定义类型,有几行;定义一个[],内容是[]int
for i := range maze { // 遍历[][]int,定义内部的[]int长度
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
}
// 因为探索方向是上左下右,这里定义探索方向
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
}
// 走迷宫,给定起点与终点
func walkByMy(maze [][]int, start point, end point) [][]int {
// 创建用于存储广度算法结果的数据
steps := make([][]int, len(maze))
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)
// 保证下一个点可通过(界限内,且不是墙)
val, ok := next.at(maze)
if !ok || val == 1 {
continue
}
// 下个点不是外部,且没有走到过(如果走到了,就不是0,除了起点,剩下走到过的地方都不是0)
val, ok = next.at(steps)
if !ok || val != 0 {
continue
}
// 下个点不是起点
if next == start {
continue
}
// 探索成功,记录成功的步骤
curSteps, _ := cur.at(steps)
steps[next.i][next.j] = curSteps + 1
// 存入队列中
Q = append(Q, next)
}
}
return steps
}
func main() {
// 读取文件,获取迷宫数据
maze := readMaze("12/maze/maze.in")
// // 输出迷宫数据,查看文件是否读取成功
// for _, row := range maze {
// for _, val := range row {
// fmt.Printf("%d ", val)
// }
// fmt.Println()
// }
// 走迷宫,假如给定其实点与结束点
steps := walkByMy(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()
}
// TODO 输出步骤数,并且输出点位置
}Last updated
Was this helpful?