侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Python迷宫生成和迷宫破解算法实例

Python  /  管理员 发布于 7年前   211

迷宫生成

1.随机PRIM

思路:先让迷宫中全都是墙,不断从列表(最初只含有一个启始单元格)中选取一个单元格标记为通路,将其周围(上下左右)未访问过的单元格放入列表并标记为已访问,再随机选取该单元格与周围通路单元格(若有的话)之间的一面墙打通。重复以上步骤直到列表为空,迷宫生成完毕。这种方式生成的迷宫难度高,岔口多。

效果:

代码:

import randomimport numpy as npfrom matplotlib import pyplot as pltdef build_twist(num_rows, num_cols): # 扭曲迷宫# (行坐标,列坐标,四面墙的有无&访问标记) m = np.zeros((num_rows, num_cols, 5), dtype=np.uint8) r, c = 0, 0 trace = [(r, c)] while trace:  r, c = random.choice(trace)  m[r, c, 4] = 1# 标记为通路  trace.remove((r, c))  check = []  if c > 0:   if m[r, c - 1, 4] == 1:    check.append('L')   elif m[r, c - 1, 4] == 0:    trace.append((r, c - 1))    m[r, c - 1, 4] = 2# 标记为已访问  if r > 0:   if m[r - 1, c, 4] == 1:    check.append('U')   elif m[r - 1, c, 4] == 0:    trace.append((r - 1, c))    m[r - 1, c, 4] = 2  if c < num_cols - 1:   if m[r, c + 1, 4] == 1:    check.append('R')   elif m[r, c + 1, 4] == 0:    trace.append((r, c + 1))    m[r, c + 1, 4] = 2  if r < num_rows - 1:   if m[r + 1, c, 4] == 1:    check.append('D')   elif m[r + 1, c, 4] == 0:    trace.append((r + 1, c))    m[r + 1, c, 4] = 2  if len(check):   direction = random.choice(check)   if direction == 'L':# 打通一面墙    m[r, c, 0] = 1    c = c - 1    m[r, c, 2] = 1   if direction == 'U':    m[r, c, 1] = 1    r = r - 1    m[r, c, 3] = 1   if direction == 'R':    m[r, c, 2] = 1    c = c + 1    m[r, c, 0] = 1   if direction == 'D':    m[r, c, 3] = 1    r = r + 1    m[r, c, 1] = 1 m[0, 0, 0] = 1 m[num_rows - 1, num_cols - 1, 2] = 1 return m

2.深度优先

思路:从起点开始随机游走并在前进方向两侧建立墙壁,标记走过的单元格,当无路可走(周围无未访问过的单元格)时重复返回上一个格子直到有新的未访问单元格可走。最终所有单元格都被访问过后迷宫生成完毕。这种方式生成的迷宫较为简单,由一条明显但是曲折的主路径和不多的分支路径组成。

效果:

代码:

def build_tortuous(num_rows, num_cols): # 曲折迷宫 m = np.zeros((num_rows, num_cols, 5), dtype=np.uint8) r = 0 c = 0 trace = [(r, c)] while trace:  m[r, c, 4] = 1# 标记为已访问  check = []  if c > 0 and m[r, c - 1, 4] == 0:   check.append('L')  if r > 0 and m[r - 1, c, 4] == 0:   check.append('U')  if c < num_cols - 1 and m[r, c + 1, 4] == 0:   check.append('R')  if r < num_rows - 1 and m[r + 1, c, 4] == 0:   check.append('D')  if len(check):   trace.append([r, c])   direction = random.choice(check)   if direction == 'L':    m[r, c, 0] = 1    c = c - 1    m[r, c, 2] = 1   if direction == 'U':    m[r, c, 1] = 1    r = r - 1    m[r, c, 3] = 1   if direction == 'R':    m[r, c, 2] = 1    c = c + 1    m[r, c, 0] = 1   if direction == 'D':    m[r, c, 3] = 1    r = r + 1    m[r, c, 1] = 1  else:   r, c = trace.pop() m[0, 0, 0] = 1 m[num_rows - 1, num_cols - 1, 2] = 1 return m

迷宫破解

效果:

1.填坑法

思路:从起点开始,不断随机选择没墙的方向前进,当处于一个坑(除了来时的方向外三面都是墙)中时,退一步并建造一堵墙将坑封上。不断重复以上步骤,最终就能抵达终点。

优缺点:可以处理含有环路的迷宫,但是处理时间较长还需要更多的储存空间。

代码:

def solve_fill(num_rows, num_cols, m): # 填坑法 map_arr = m.copy()# 拷贝一份迷宫来填坑 map_arr[0, 0, 0] = 0 map_arr[num_rows-1, num_cols-1, 2] = 0 move_list = [] xy_list = [] r, c = (0, 0) while True:  if (r == num_rows-1) and (c == num_cols-1):   break  xy_list.append((r, c))  wall = map_arr[r, c]  way = []  if wall[0] == 1:   way.append('L')  if wall[1] == 1:   way.append('U')  if wall[2] == 1:   way.append('R')  if wall[3] == 1:   way.append('D')  if len(way) == 0:   return False  elif len(way) == 1:# 在坑中   go = way[0]   move_list.append(go)   if go == 'L':# 填坑    map_arr[r, c, 0] = 0    c = c - 1    map_arr[r, c, 2] = 0   elif go == 'U':    map_arr[r, c, 1] = 0    r = r - 1    map_arr[r, c, 3] = 0   elif go == 'R':    map_arr[r, c, 2] = 0    c = c + 1    map_arr[r, c, 0] = 0   elif go == 'D':    map_arr[r, c, 3] = 0    r = r + 1    map_arr[r, c, 1] = 0  else:   if len(move_list) != 0:# 不在坑中    come = move_list[len(move_list)-1]    if come == 'L':     if 'R' in way:      way.remove('R')    elif come == 'U':     if 'D' in way:      way.remove('D')    elif come == 'R':     if 'L' in way:      way.remove('L')    elif come == 'D':     if 'U' in way:      way.remove('U')   go = random.choice(way)# 随机选一个方向走   move_list.append(go)   if go == 'L':    c = c - 1   elif go == 'U':    r = r - 1   elif go == 'R':    c = c + 1   elif go == 'D':    r = r + 1 r_list = xy_list.copy() r_list.reverse()# 行动坐标记录的反转 i = 0 while i < len(xy_list)-1:# 去掉重复的移动步骤  j = (len(xy_list)-1) - r_list.index(xy_list[i])  if i != j:# 说明这两个坐标之间的行动步骤都是多余的,因为一顿移动回到了原坐标   del xy_list[i:j]   del move_list[i:j]   r_list = xy_list.copy()   r_list.reverse()  i = i + 1 return move_list

2.回溯法

思路:遇到岔口则将岔口坐标和所有可行方向压入栈,从栈中弹出一个坐标和方向,前进。不断重复以上步骤,最终就能抵达终点。

优缺点:计算速度快,需要空间小,但无法处理含有环路的迷宫。

代码:

def solve_backtrack(num_rows, num_cols, map_arr): # 回溯法 move_list = ['R'] m = 1# 回溯点组号 mark = [] r, c = (0, 0) while True:  if (r == num_rows-1) and (c == num_cols-1):   break  wall = map_arr[r, c]  way = []  if wall[0] == 1:   way.append('L')  if wall[1] == 1:   way.append('U')  if wall[2] == 1:   way.append('R')  if wall[3] == 1:   way.append('D')  come = move_list[len(move_list) - 1]  if come == 'L':   way.remove('R')  elif come == 'U':   way.remove('D')  elif come == 'R':   way.remove('L')  elif come == 'D':   way.remove('U')  while way:   mark.append((r, c, m, way.pop()))# 记录当前坐标和可行移动方向  if mark:   r, c, m, go = mark.pop()   del move_list[m:]# 删除回溯点之后的移动  else:   return False  m = m + 1  move_list.append(go)  if go == 'L':   c = c - 1  elif go == 'U':   r = r - 1  elif go == 'R':   c = c + 1  elif go == 'D':   r = r + 1 del move_list[0] return move_list

测试

rows = int(input("Rows: "))cols = int(input("Columns: "))Map = build_twist(rows, cols)plt.imshow(draw(rows, cols, Map), cmap='gray')fig = plt.gcf()fig.set_size_inches(cols/10/3, rows/10/3)plt.gca().xaxis.set_major_locator(plt.NullLocator())plt.gca().yaxis.set_major_locator(plt.NullLocator())plt.subplots_adjust(top=1, bottom=0, right=1, left=0, hspace=0, wspace=0)plt.margins(0, 0)fig.savefig('aaa.png', format='png', transparent=True, dpi=300, pad_inches=0)move = solve_backtrack(rows, cols, Map)plt.imshow(draw_path(draw(rows, cols, Map), move), cmap='hot')fig = plt.gcf()fig.set_size_inches(cols/10/3, rows/10/3)plt.gca().xaxis.set_major_locator(plt.NullLocator())plt.gca().yaxis.set_major_locator(plt.NullLocator())plt.subplots_adjust(top=1, bottom=0, right=1, left=0, hspace=0, wspace=0)plt.margins(0, 0)fig.savefig('bbb.png', format='png', transparent=True, dpi=300, pad_inches=0)

以上这篇Python迷宫生成和迷宫破解算法实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。


  • 上一条:
    python 利用已有Ner模型进行数据清洗合并代码
    下一条:
    Python3 A*寻路算法实现方式
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客