迷宫生成
1.随机PRIM
思路:先让迷宫中全都是墙,不断从列表(最初只含有一个启始单元格)中选取一个单元格标记为通路,将其周围(上下左右)未访问过的单元格放入列表并标记为已访问,再随机选取该单元格与周围通路单元格(若有的话)之间的一面墙打通。重复以上步骤直到列表为空,迷宫生成完毕。这种方式生成的迷宫难度高,岔口多。
效果:
代码:
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.深度优先
思路:从起点开始随机游走并在前进方向两侧建立墙壁,标记走过的单元格,当无路可走(周围无未访问过的单元格)时重复返回上一个格子直到有新的未访问单元格可走。最终所有单元格都被访问过后迷宫生成完毕。这种方式生成的迷宫较为简单,由一条明显但是曲折的主路径和不多的分支路径组成。
效果:
代码:
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