使用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 相关文章推荐
python3访问sina首页中文的处理方法
Feb 24 Python
跟老齐学Python之深入变量和引用对象
Sep 24 Python
为Python的web框架编写MVC配置来使其运行的教程
Apr 30 Python
python控制台中实现进度条功能
Nov 10 Python
Python set常用操作函数集锦
Nov 15 Python
Python实现七彩蟒蛇绘制实例代码
Jan 16 Python
Python实现的查询mysql数据库并通过邮件发送信息功能
May 17 Python
Python标准库shutil用法实例详解
Aug 13 Python
python3实现zabbix告警推送钉钉的示例
Feb 20 Python
python如何求圆的面积
Jul 01 Python
Python接收手机短信的代码整理
Aug 02 Python
用sleep间隔进行python反爬虫的实例讲解
Nov 30 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数组内存耗用太多问题的解决方法
2010/04/05 PHP
利用PHP实现智能文件类型检测的实现代码
2011/08/02 PHP
基于php伪静态的实现详细介绍
2013/04/28 PHP
不同的jQuery API来处理不同的浏览器事件
2012/12/09 Javascript
jquery固定底网站底部菜单效果
2013/08/13 Javascript
可自定义速度的js图片无缝滚动示例分享
2014/01/20 Javascript
原生Javascript封装的一个AJAX函数分享
2014/10/11 Javascript
详谈javascript异步编程
2016/02/21 Javascript
微信小程序 定位到当前城市实现实例代码
2017/02/23 Javascript
js实现适配不同的屏幕大小
2017/04/10 Javascript
JS自定义滚动条效果简单实现代码
2020/10/27 Javascript
JavaScript强制类型转换和隐式类型转换操作示例
2019/05/01 Javascript
JS字符串与二进制的相互转化实例代码详解
2019/06/28 Javascript
python获取豆瓣电影简介代码分享
2014/01/16 Python
Linux下使用python调用top命令获得CPU利用率
2015/03/10 Python
Using Django with GAE Python 后台抓取多个网站的页面全文
2016/02/17 Python
python自动发邮件总结及实例说明【推荐】
2019/05/31 Python
浅谈Django中view对数据库的调用方法
2019/07/18 Python
scikit-learn线性回归,多元回归,多项式回归的实现
2019/08/29 Python
python调用win32接口进行截图的示例
2020/11/11 Python
HTML5 Canvas draw方法制作动画效果示例
2013/07/11 HTML / CSS
GUESS西班牙官方网上商城:美国服饰品牌
2017/03/15 全球购物
BookOutlet加拿大:在网上书店购买廉价折扣图书和小说
2018/10/05 全球购物
瑞士设计师家具和家居饰品网上商店:Bruno Wickart
2019/03/18 全球购物
自我评价怎么写正确呢?
2013/12/02 职场文书
违反工作纪律检讨书
2014/02/15 职场文书
政治表现评语
2014/05/04 职场文书
技校毕业生自荐书
2014/05/23 职场文书
党的群众教育实践活动实施方案
2014/06/12 职场文书
自愿解除劳动合同协议书
2014/09/11 职场文书
2015年社区统计工作总结
2015/04/21 职场文书
2015年基建工作总结范文
2015/05/23 职场文书
教师节老师寄语
2015/05/28 职场文书
解决MultipartFile.transferTo(dest) 报FileNotFoundExcep的问题
2021/07/01 Java/Android
python读取并查看npz/npy文件数据以及数据显示方法
2022/04/14 Python
html网页引入svg图片的4种方式
2022/08/05 HTML / CSS