使用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 相关文章推荐
python用装饰器自动注册Tornado路由详解
Feb 14 Python
Apache如何部署django项目
May 21 Python
Python Selenium Cookie 绕过验证码实现登录示例代码
Apr 10 Python
浅谈pycharm下找不到sqlalchemy的问题
Dec 03 Python
pyqt5中QThread在使用时出现重复emit的实例
Jun 21 Python
Python实现制度转换(货币,温度,长度)
Jul 14 Python
pygame库实现俄罗斯方块小游戏
Oct 29 Python
Django2 连接MySQL及model测试实例分析
Dec 10 Python
Python序列类型的打包和解包实例
Dec 21 Python
150行python代码实现贪吃蛇游戏
Apr 24 Python
python中类与对象之间的关系详解
Dec 16 Python
详解NumPy中的线性关系与数据修剪压缩
May 25 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
提升PHP速度全攻略
2006/10/09 PHP
PHP文件注释标记及规范小结
2012/04/01 PHP
PHP读取大文件末尾N行的高效方法推荐
2016/06/03 PHP
PHP实现找出链表中环的入口节点
2018/01/16 PHP
js中将多个语句写成一个语句的两种方法小结
2007/12/08 Javascript
jquery无缝向上滚动实现代码
2013/03/29 Javascript
JavaScript:new 一个函数和直接调用函数的区别分析
2013/07/10 Javascript
Ext中下拉列表ComboBox组件store数据格式用法介绍
2013/07/15 Javascript
Javascript中引用示例介绍
2014/02/21 Javascript
JavaScript中的console.log()函数详细介绍
2014/12/29 Javascript
JS+CSS实现感应鼠标渐变显示DIV层的方法
2015/02/20 Javascript
JQuery 封装 Ajax 常用方法(推荐)
2017/05/21 jQuery
关于vue.js v-bind 的一些理解和思考
2017/06/06 Javascript
微信小游戏之使用three.js 绘制一个旋转的三角形
2019/06/10 Javascript
vue实现滑动切换效果(仅在手机模式下可用)
2020/06/29 Javascript
微信小程序 如何保持登录状态
2019/08/16 Javascript
解决layer.open后laydate失效的问题
2019/09/06 Javascript
Python中运行并行任务技巧
2015/02/26 Python
Python贪吃蛇游戏编写代码
2020/10/26 Python
python图像处理入门(一)
2019/04/04 Python
python实现坦克大战游戏 附详细注释
2020/03/27 Python
使用Python中的reduce()函数求积的实例
2019/06/28 Python
Python在终端通过pip安装好包以后在Pycharm中依然无法使用的问题(三种解决方案)
2020/03/10 Python
django使用F方法更新一个对象多个对象字段的实现
2020/03/28 Python
详解python with 上下文管理器
2020/09/02 Python
Python爬虫之Selenium实现键盘事件
2020/12/04 Python
使用sublime text3搭建Python编辑环境的实现
2021/01/12 Python
html5自动播放mov格式视频的实例代码
2020/01/14 HTML / CSS
总经理助理岗位职责
2013/11/08 职场文书
升职自荐书范文
2013/11/28 职场文书
质量承诺书格式
2014/05/20 职场文书
施工安全责任书范本
2014/07/24 职场文书
党的群众路线教育实践活动方案
2014/10/31 职场文书
党员群众路线教育实践活动学习笔记
2014/11/05 职场文书
工作保证书
2015/01/17 职场文书
学校隐患排查制度
2015/08/05 职场文书