go实现迷宫算法

要求

    从迷宫的起点走到终点,其中0表示可走,1表示不可走

a)迷宫 b) c)d)

 

思路

    1、给每个点标坐标,按逆时针方向探索可行点,并将其入队。

    2、首先探索(0, 0)附近可行点,只有(1, 0),因此(1, 0)入队

    3、(1, 0)出队,探索(1, 0)附近可行点,有(2, 0)和(1, 1)2个点,这2个点入队

    4、(2, 0)出队,探索附近可行点,并将可行点加入队列

    5、(1, 1)出队,探索附近可行点,并将可行点加入队列

    6、依次类推,直至探索到终点(5, 4)为止,或者探索到队列为空,说明不存在路径可达起点到终点。

    7、为每一个坐标标上所走步数,从终点往起点推,每一个点附近只有一个上一个步数,因此可以得到最终路径

以上思路实际上一个广度优先算法。

go实现

package main

import (
	"fmt"
)

/**
迷宫如下:6行5列,0代表可走,1代表不可走,只能上下左右走,不能斜着走
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
坐上角开始,右下角结束。要求走出最短路径
 */

type point struct {
	i, j int
}

//每个点有4个方向,上左下右
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}
}

//返回值int代表当前点step,bool表示是否越界(坐标超过grid)
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(mazi [][]int, start, end point) [][]int {
	steps := make([][]int, len(mazi)) //走到该坐标所需步数数组
	for i := range steps {
		steps[i] = make([]int, len(mazi[0]))
	}

	//队列
	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)

			//探索可行节点
			//1.next不是墙,即值=0
			//2.next的没走过,即step为0
			//3.next != start
			val, ok := next.at(mazi)
			if !ok || val == 1 { //剔除不能走的情况
				continue
			}

			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 findPath(steps [][]int) []point {
	start  := point{0,0}
	poi := point{len(steps)-1, len(steps[0])-1}
	value := steps[len(steps)-1][len(steps[0])-1]
	var list = []point{poi}
	for poi != start {
		for _, dir := range dirs  {
			last := poi.add(dir)
			//判断是否越界
			if _, ok := last.at(steps); ok {
				if steps[last.i][last.j] == (value - 1) {
					list = append(list, last)
					poi = last
					value --
					break
				}
			}
		}
	}

	return list
}

func main() {
	maze := [][]int{
		{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}}

	steps := walk(maze, point{0, 0}, point{len(maze)-1, len(maze[0])-1})
	fmt.Println("迷宫步数图:")
	for _, row := range steps {
		for _, val := range row {
			fmt.Printf("%3d", val)
		}
		fmt.Println()
	}

	fmt.Println("最短需要走的步数:", steps[len(maze)-1][len(maze[0])-1])
	fmt.Print("最短路径坐标为:")
	paths := findPath(steps)
	for i := len(paths) -1; i >= 0; i-- {
		fmt.Printf("(%d, %d) ", paths[i].i, paths[i].j)
	}
}


/*
迷宫步数图:
0  0  4  5  6
1  2  3  0  7
2  0  4  0  8
0  0  0 10  9
0  0 12 11  0
0  0 13 12 13
*/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值