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抓取网页图片并放到指定文件夹
Apr 24 Python
python Socket之客户端和服务端握手详解
Sep 18 Python
Python2和Python3中print的用法示例总结
Oct 25 Python
Python中的函数作用域
May 07 Python
python的pip安装以及使用教程
Sep 18 Python
python中实现控制小数点位数的方法
Jan 24 Python
Python日期时间Time模块实例详解
Apr 15 Python
Python pip替换为阿里源的方法步骤
Jul 02 Python
Django 实现Admin自动填充当前用户的示例代码
Nov 18 Python
更新升级python和pip版本后不生效的问题解决
Apr 17 Python
python有几个版本
Jun 17 Python
python3判断IP地址的方法
Mar 04 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读取文件内容后清空文件示例代码
2014/03/18 PHP
php中file_get_content 和curl以及fopen 效率分析
2014/09/19 PHP
php通过正则表达式记取数据来读取xml的方法
2015/03/09 PHP
Laravel最佳分割路由文件(routes.php)的方式
2016/08/04 PHP
php获取ajax的headers方法与内容实例
2017/12/27 PHP
PHP实现微信退款的方法示例
2019/03/26 PHP
Javascript 获取字符串字节数的多种方法
2009/06/02 Javascript
7个JS基础知识总结
2014/03/05 Javascript
最简单的tab切换实例代码
2016/05/13 Javascript
基于angular中的重要指令详解($eval,$parse和$compile)
2016/10/21 Javascript
详解Angular如何正确的操作DOM
2018/07/06 Javascript
layui表单验证select下拉框实现验证的方法
2019/09/05 Javascript
Layui表格监听行单双击事件讲解
2019/11/14 Javascript
vue-router 路由传参用法实例分析
2020/03/06 Javascript
详解vue高级特性
2020/06/09 Javascript
JS实现电脑虚拟键盘的操作
2020/06/24 Javascript
vue-admin-template配置快捷导航的代码(标签导航栏)
2020/09/04 Javascript
[57:22]2018DOTA2亚洲邀请赛 4.7总决赛 LGD vs Mineski 第五场
2018/04/10 DOTA
python端口扫描系统实现方法
2014/11/19 Python
python扫描proxy并获取可用代理ip的实例
2017/08/07 Python
python 信息同时输出到控制台与文件的实例讲解
2018/05/11 Python
python解析含有重复key的json方法
2019/01/22 Python
django框架实现模板中获取request 的各种信息示例
2019/07/01 Python
Python爬虫抓取技术的一些经验
2019/07/12 Python
Python单元测试与测试用例简析
2019/11/09 Python
Windows10下Tensorflow2.0 安装及环境配置教程(图文)
2019/11/21 Python
Python如何生成xml文件
2020/06/04 Python
Python中猜拳游戏与猜筛子游戏的实现方法
2020/09/04 Python
如何在pycharm中安装第三方包
2020/10/27 Python
HTML5 Canvas自定义圆角矩形与虚线示例代码
2013/08/02 HTML / CSS
化验室技术员岗位职责
2013/12/24 职场文书
小学生期末评语
2014/04/21 职场文书
高中教师考核方案
2014/05/18 职场文书
授权委托书样本及填写说明
2014/09/19 职场文书
法人身份证明书
2014/10/08 职场文书
婚庆主持词大全
2015/06/30 职场文书