zoukankan      html  css  js  c++  java
  • Go 迷宫算法

    首先读取一个迷宫文件maze.in (第一行是文件的行列  下面是文件内容:1表示墙 0表示此路可走)

    如何读取?

    //读取一个二维数组 
    func readMaze(filename string) [][]int {
        // 先打开文件 默认是已经存在这个文件 故没有做其他出错处理
        file, err := os.Open(filename)  
        if err != nil {
            panic(err)
        }
        //需要先将行、列读出来 利用Fscanf读取
        var row, col int
        fmt.Fscanf(file, "%d %d", &row, &col)
        //创建二维slice 注意:这里是传入参数行row 因为二维数组其实就是:有row这么多一维数组构成 这里是使用切片
        maze := make([][]int, row)
        for i := range maze {
            maze[i] = make([]int, col)  //利用make创建
            for j := range maze[i] {
                fmt.Fscanf(file, "%d", &maze[i][j])
            }
        }
        return maze
    }
    
    func main() {
        maze := readMaze("mazepractice/maze.in")
        for _,row := range maze {
            for _,val := range row {
                fmt.Printf("%3d",val)
            }
            fmt.Println()
        }
    }

     迷宫算法解读

    package main
    
    import (
        "fmt"
        "os"
    )
    
    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)
    
        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
    }
    // 定义点的结构体 因为这里是数组 最好不要用x,y定义(以免自己与坐标混淆)
    type point struct {
        i, j int
    }
    // 定义4个方向分别是:上 左 下 右 方向
    var dirs = [4]point{
        {-1, 0}, {0, -1}, {1, 0}, {0, 1}}
    // 走迷宫需要从上左下右方向去走,因此坐标会相应的变化  注:这里是利用返回一个新的point 而不是利用指针(当然,指针也可以)
    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
    }
    // 走迷宫的关键算法 通过传入3个参数:二维切片,开始点,结束点  返回的是:一个二维切片
    func walk(maze [][]int, start, end point) [][]int {
        // 这里其实是创建一个走过路线的steps 根据我们读取的文件maze.in规格大小来创建
        steps := make([][]int, len(maze))
        for i := range steps {
            steps[i] = make([]int, len(maze[i]))
        }
        // 创建一个队列 开始点是(0,0)
        Q := []point{start}
        // 队列不空
        for len(Q) > 0 {
            cur := Q[0]  //cur代表队列开始点(0,0)
            Q = Q[1:]    //去掉队列第一个点
            // 发现终点 退出
            if cur == end {
                break
            }
           // 没有走到的请看
            for _, dir := range dirs {
                // 通过上 左 下 右 走这些路
                next := cur.add(dir)
                // 判断走的路线是不是可以走:0 可以走  1 不可以走  当然越界也是不行的
                val, ok := next.at(maze)
                if !ok || val == 1 {
                    continue
                }
                // 判断这些点有没有走过:就是不要走回头路
                val, ok = next.at(steps)
                if !ok || val != 0 {
                    continue
                }
                // 不是0 可能回到起点 不行的
                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("mazepractice/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()
        }
        lessStep := steps[len(maze)-1][len(maze[0])-1]
        fmt.Printf("这个迷宫最少需要%d步走完",lessStep)
        // TODO: construct path from steps
    
    }

     左边是读取的文件,右边是输出结果:

     

     左边是读取的文件,右边是输出结果:

  • 相关阅读:
    设置GridView、DataGrid 以提供thead、tbody等标签
    SqlCommandBuilder 可批量新增与修改数据
    js中的截流
    react代码分离方案
    redux在react中的使用
    react 生命周期
    react 函数bind(this)的三种方式
    react 三种组件定义方式
    linux系统下nginx安装目录和nginx.conf配置文件目录
    react component lifecycle
  • 原文地址:https://www.cnblogs.com/ycx95/p/9397920.html
Copyright © 2011-2022 走看看