使用python求解迷宫问题的三种实现方法


Posted in Python onMarch 17, 2022

前言

在迷宫问题中,给定入口和出口,要求找到路径。本文将讨论三种求解方法,递归求解、回溯求解和队列求解。

在介绍具体算法之前,先考虑将迷宫数字化。这里将迷宫用一个二维的list存储(即list嵌套在list里),将不可到达的位置用1表示,可到达的位置用0表示,并将已经到过的位置用2表示。

使用python求解迷宫问题的三种实现方法

递归求解

递归求解的基本思路是:

  • 每个时刻总有一个当前位置,开始时这个位置是迷宫人口。
  • 如果当前位置就是出口,问题已解决。
  • 否则,如果从当前位置己无路可走,当前的探查失败,回退一步。
  • 取一个可行相邻位置用同样方式探查,如果从那里可以找到通往出口的路径,那么从当前位置到出口的路径也就找到了。

在整个计算开始时,把迷宫的人口(序对)作为检查的当前位置,算法过程就是:

  • mark当前位置。
  • 检查当前位置是否为出口,如果是则成功结束。
  • 逐个检查当前位置的四邻是否可以通达出口(递归调用自身)。
  • 如果对四邻的探索都失败,报告失败。
dirs=[(0,1),(1,0),(0,-1),(-1,0)] #当前位置四个方向的偏移量
path=[]              #存找到的路径
 
def mark(maze,pos):  #给迷宫maze的位置pos标"2"表示“倒过了”
    maze[pos[0]][pos[1]]=2
 
def passable(maze,pos): #检查迷宫maze的位置pos是否可通行
    return maze[pos[0]][pos[1]]==0
 
def find_path(maze,pos,end):
    mark(maze,pos)
    if pos==end:
        print(pos,end=" ")  #已到达出口,输出这个位置。成功结束
        path.append(pos)
        return True
    for i in range(4):      #否则按四个方向顺序检查
        nextp=pos[0]+dirs[i][0],pos[1]+dirs[i][1]
        #考虑下一个可能方向
        if passable(maze,nextp):        #不可行的相邻位置不管
            if find_path(maze,nextp,end):#如果从nextp可达出口,输出这个位置,成功结束
                print(pos,end=" ")
                path.append(pos)
                return True
    return False
 
def see_path(maze,path):     #使寻找到的路径可视化
    for i,p in enumerate(path):
        if i==0:
            maze[p[0]][p[1]] ="E"
        elif i==len(path)-1:
            maze[p[0]][p[1]]="S"
        else:
            maze[p[0]][p[1]] =3
    print("\n")
    for r in maze:
        for c in r:
            if c==3:
                print('\033[0;31m'+"*"+" "+'\033[0m',end="")
            elif c=="S" or c=="E":
                print('\033[0;34m'+c+" " + '\033[0m', end="")
            elif c==2:
                print('\033[0;32m'+"#"+" "+'\033[0m',end="")
            elif c==1:
                print('\033[0;;40m'+" "*2+'\033[0m',end="")
            else:
                print(" "*2,end="")
        print()
 
if __name__ == '__main__':
    maze=[[1,1,1,1,1,1,1,1,1,1,1,1,1,1],\
          [1,0,0,0,1,1,0,0,0,1,0,0,0,1],\
          [1,0,1,0,0,0,0,1,0,1,0,1,0,1],\
          [1,0,1,0,1,1,1,1,0,1,0,1,0,1],\
          [1,0,1,0,0,0,0,0,0,1,1,1,0,1],\
          [1,0,1,1,1,1,1,1,1,1,0,0,0,1],\
          [1,0,1,0,0,0,0,0,0,0,0,1,0,1],\
          [1,0,0,0,1,1,1,0,1,0,1,1,0,1],\
          [1,0,1,0,1,0,1,0,1,0,1,0,0,1],\
          [1,0,1,0,1,0,1,0,1,1,1,1,0,1],\
          [1,0,1,0,0,0,1,0,0,1,0,0,0,1],\
          [1,1,1,1,1,1,1,1,1,1,1,1,1,1]]
    start=(1,1)
    end=(10,12)
    find_path(maze,start,end)
    see_path(maze,path)

代码中see_path函数可以在控制台直观打印出找到的路径,打印结果如下:

使用python求解迷宫问题的三种实现方法

S是入口位置 ,E是出口位置,*代表找到的路径,#代表探索过的路径。

回溯求解

在回溯解法中,主要是用栈来存储可以探索的位置。利用栈后进先出的特点,在一条分路上探索失败时,回到最近一次存储的可探索位置。这是一种深度优先搜索的方法。

def maze_solver(maze,start,end):
    if start==end:
        print(start)
        return
    st=SStack()
    mark(maze,start)
    st.push((start,0))             #入口和方向0的序对入栈
    while not st.is_empty():      #走不通时回退
        pos,nxt=st.pop()           #取栈顶及其检查方向
        for i in range(nxt,4):     #依次检查未检查方向,算出下一位置
            nextp = pos[0] + dirs[i][0], pos[1] + dirs[i][1]
            if nextp==end:
                print_path(end,pos,st)  #到达出口,打印位置
                return
            if passable(maze,nextp):    #遇到未探索的新位置
                st.push((pos,i+1))      #原位置和下一方向入栈
                mark(maze,nextp)
                st.push((nextp,0))      #新位置入栈
                break                   #退出内层循环,下次迭代将以新栈顶作为当前位置继续
    print("找不到路径")

队列求解

队列求解算法中,以队列存储可以探索的位置。利用队列先进先出的特点,实现在每个分支上同时进行搜索路径,直到找到出口。这是一种广度优先搜索的方法。

def maze_solver_queue(maze,start,end):
   path.append(start)
   if start==end:
       print("找到路径")
       return
   qu=SQueue()
   mark(maze,start)
   qu.enqueue(start)                #start位置入队
   while not qu.is_empty():        #还有候选位置
       pos=qu.dequeue()             #取出下一位置
       for i in range(4):           #检查每个方向
           nextp = pos[0] + dirs[i][0], pos[1] + dirs[i][1]
           if passable(maze,nextp): #找到新的探索方向
               if nextp==end:       #是出口,成功
                   print("找到路径")
                   path.append(end)
                   return
               mark(maze,nextp)
               qu.enqueue(nextp)    #新位置入队
               path.append(nextp)
 
   print("未找到路径")

但队列求解方法,不能直接得出找到的具体路径,要得到找到的路径还需要其他存储结构(如链表)。

总结

到此这篇关于使用python求解迷宫问题的三种实现方法的文章就介绍到这了,更多相关python求解迷宫问题内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
centos 下面安装python2.7 +pip +mysqld
Nov 18 Python
python回调函数用法实例分析
May 09 Python
python3实现ftp服务功能(服务端 For Linux)
Mar 24 Python
基于Linux系统中python matplotlib画图的中文显示问题的解决方法
Jun 15 Python
Python基于回溯法子集树模板实现8皇后问题
Sep 01 Python
python使用zip将list转为json的方法
Dec 31 Python
python调用matplotlib模块绘制柱状图
Oct 18 Python
Pytorch to(device)用法
Jan 08 Python
Python调用Windows命令打印文件
Feb 07 Python
python GUI库图形界面开发之pyinstaller打包python程序为exe安装文件
Feb 26 Python
python 判断一组数据是否符合正态分布
Sep 23 Python
Python与C++中梯度方向直方图的实现
Mar 17 Python
Python超详细分步解析随机漫步
yolov5返回坐标的方法实例
Mar 17 #Python
PyTorch中的torch.cat简单介绍
Mar 17 #Python
Python Pygame实战在打砖块游戏的实现
python超详细实现完整学生成绩管理系统
Mar 17 #Python
Python Pygame实战之塔防游戏的实现
pytorch中的 .view()函数的用法介绍
Mar 17 #Python
You might like
Symfony生成二维码的方法
2016/02/04 PHP
再说AutoComplete自动补全之实现原理
2011/11/05 Javascript
jQuery Tools tooltip使用说明
2012/07/14 Javascript
原生js 秒表实现代码
2012/07/24 Javascript
使用按钮控制以何种方式打开新窗口的属性介绍
2012/12/17 Javascript
使用 Node.js 做 Function Test实现方法
2013/10/25 Javascript
使用js实现关闭js弹出层的窗口
2014/02/10 Javascript
jquery弹窗插件colorbox绑定动态生成元素的方法
2014/06/20 Javascript
教你如何使用firebug调试功能了解javascript闭包和this
2015/03/04 Javascript
JavaScript实现表格快速变色效果代码
2015/08/19 Javascript
jQuery+PHP星级评分实现方法
2015/10/02 Javascript
Ionic实现页面下拉刷新(ion-refresher)功能代码
2016/06/03 Javascript
JS控制页面跳转时未请求要跳转的地址怎么回事
2016/10/14 Javascript
JS扩展类,克隆对象与混合类实例分析
2016/11/26 Javascript
详解有关easyUI的拖动操作中droppable,draggable用法例子
2017/06/03 Javascript
浅谈vue中数据双向绑定的实现原理
2017/09/14 Javascript
layerUI下的绑定事件实例代码
2018/08/17 Javascript
vue 搭建后台系统模块化开发详解
2019/05/01 Javascript
[00:12]DAC2018 天才少年转战三号位,他的SOLO是否仍如昔日般强大?
2018/04/06 DOTA
Python自定义进程池实例分析【生产者、消费者模型问题】
2016/09/19 Python
python如何创建TCP服务端和客户端
2018/08/26 Python
Python实现正则表达式匹配任意的邮箱方法
2018/12/20 Python
python实现扫描局域网指定网段ip的方法
2019/04/16 Python
详解python中自定义超时异常的几种方法
2019/07/29 Python
python zip()函数使用方法解析
2019/10/31 Python
Django执行源生mysql语句实现过程解析
2020/11/12 Python
Python 实现PS滤镜中的径向模糊特效
2020/12/03 Python
HTML5中form如何关闭自动完成功能的方法
2018/07/02 HTML / CSS
ECCO爱步美国官网:来自丹麦的鞋履品牌
2016/11/23 全球购物
英国最受欢迎的价格比较网站之一:MoneySuperMarket
2018/12/19 全球购物
英国礼品和生活方式品牌:Treat Republic
2020/11/21 全球购物
医生进修自我鉴定
2014/01/19 职场文书
社区助残日活动总结
2014/08/29 职场文书
借条格式范本
2015/05/25 职场文书
如何Python使用re模块实现okenizer
2022/04/30 Python
GoFrame基于性能测试得知grpool使用场景
2022/06/21 Golang