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


Posted in Python onDecember 24, 2019

迷宫生成

1.随机PRIM

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

效果:

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

代码:

import random
import numpy as np
from matplotlib import pyplot as plt


def 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.深度优先

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

效果:

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

代码:

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

迷宫破解

效果:

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

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

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 相关文章推荐
Python中map,reduce,filter和sorted函数的使用方法
Aug 17 Python
不要用强制方法杀掉python线程
Feb 26 Python
Python使用三种方法实现PCA算法
Dec 12 Python
Django学习教程之静态文件的调用详解
May 08 Python
Selenium控制浏览器常见操作示例
Aug 13 Python
对Python3 序列解包详解
Feb 16 Python
Python栈的实现方法示例【列表、单链表】
Feb 22 Python
python高阶函数map()和reduce()实例解析
Mar 16 Python
基于python实现FTP文件上传与下载操作(ftp&amp;sftp协议)
Apr 01 Python
python如何编写win程序
Jun 08 Python
浅谈TensorFlow中读取图像数据的三种方式
Jun 30 Python
Python map及filter函数使用方法解析
Aug 06 Python
Python3 A*寻路算法实现方式
Dec 24 #Python
python logging添加filter教程
Dec 24 #Python
python打印异常信息的两种实现方式
Dec 24 #Python
numpy实现神经网络反向传播算法的步骤
Dec 24 #Python
python异常处理和日志处理方式
Dec 24 #Python
Python 音频生成器的实现示例
Dec 24 #Python
Python concurrent.futures模块使用实例
Dec 24 #Python
You might like
用PHP制作的意见反馈表源码
2007/03/11 PHP
php桌面中心(三) 修改数据库
2007/03/11 PHP
SWFUpload与CI不能正确上传识别文件MIME类型解决方法分享
2011/04/18 PHP
PHP生成唯一的促销/优惠/折扣码(附源码)
2012/12/28 PHP
Linux编译升级php的详细方法
2013/11/04 PHP
PHP判断文章里是否有图片的简单方法
2014/07/26 PHP
php微信开发之批量生成带参数的二维码
2016/06/26 PHP
jqGrid jQuery 表格插件测试代码
2011/08/23 Javascript
js nextSibling属性和previousSibling属性概述及使用注意
2013/02/16 Javascript
JS制作简单的三级联动
2015/03/18 Javascript
Node.js返回JSONP详解
2016/05/18 Javascript
JS简单实现点击复制链接的方法
2016/08/03 Javascript
AngularJS实现给动态生成的元素绑定事件的方法
2016/12/14 Javascript
微信小程序实战之仿android fragment可滑动底部导航栏(4)
2020/04/16 Javascript
vuejs使用$emit和$on进行组件之间的传值的示例
2017/10/04 Javascript
vue2.0获取鼠标位置的方法
2018/09/13 Javascript
layui自定义工具栏的方法
2019/09/19 Javascript
Vue如何基于vue-i18n实现多国语言兼容
2020/07/17 Javascript
vue使用canvas实现移动端手写签名
2020/09/22 Javascript
微信小程序自定义底部弹出框功能
2020/11/18 Javascript
[01:00:52]2018DOTA2亚洲邀请赛 4.4 淘汰赛 EG vs LGD 第一场
2018/04/05 DOTA
Python中的闭包总结
2014/09/18 Python
Python的Django框架中的表单处理示例
2015/07/17 Python
Python中max函数用于二维列表的实例
2018/04/03 Python
Python数据分析库pandas基本操作方法
2018/04/08 Python
Pandas中把dataframe转成array的方法
2018/04/13 Python
Django unittest 设置跳过某些case的方法
2018/12/26 Python
Python函数装饰器原理与用法详解
2019/08/16 Python
html5中的一些标签学习(心得)
2016/10/18 HTML / CSS
Sneaker Studio法国:购买运动鞋
2018/06/08 全球购物
教你打造完美的创业计划书
2014/01/06 职场文书
小学生保护环境倡议书
2014/05/15 职场文书
2015年高一班主任工作总结
2015/05/13 职场文书
团队拓展训练心得体会
2016/01/12 职场文书
《风娃娃》教学反思
2016/02/18 职场文书
python numpy中multiply与*及matul 的区别说明
2021/05/26 Python