使用PIL生成环形迷宫的问题排查与解决请求
环形迷宫生成程序问题修复
问题1:墙体线条不完整、长度不足
问题原因
- 未绘制中心区域(level 0)的外围圆弧和最外层的完整外圆弧
- 径向墙仅绘制了
line_length长度,未覆盖整个层级的径向宽度(line_length + corridor_size) - 左侧墙体重复绘制,部分边界未闭合
修复方案
- 补充中心区域外围圆弧和最外层外圆弧,确保迷宫边界完整
- 修正径向墙的终点坐标,使其连接到上一层级的半径,覆盖完整层级宽度
- 调整墙体绘制逻辑,避免重复绘制分隔墙
问题2:层级单元格数量变化时衔接偏差
问题原因
- 单元格数量翻倍时,子层级径向墙的角度未与父层级的单元格边界精准对齐
- 角度计算未考虑层级间单元格数量的比例关系,导致视觉偏差
修复方案
- 优化单元格数量计算逻辑,确保层级间数量变化仅为1倍或2倍,保持角度比例一致
- 调整径向墙的角度计算,使其严格对齐父层级的单元格角度范围
- 统一使用弧度计算角度,减少浮点误差
修改后的完整代码
from PIL import Image, ImageDraw import math import random from collections import deque class CircularMaze: def __init__(self, levels, line_len, wall_width, corridor_size, canvas_size): assert line_len > 0, "Line length must be greater than 0" self.canvas_size = canvas_size self.num_levels = levels self.line_length = line_len self.wall_width = wall_width self.corridor_size = corridor_size self.num_cells_at_level = self.cell_count_by_level() self.total_cells = sum(self.num_cells_at_level) def cell_count_by_level(self): # 优化单元格数量增长逻辑:从8开始,每2^n层翻倍,确保层级间数量为1或2倍关系 cells_by_level = [1] base_cells = 8 current_cells = base_cells # 确定每个层级的单元格数量 for level in range(1, self.num_levels): # 每经过2^k层,单元格数量翻倍(k从0开始) if level == 2 ** (len(bin(current_cells)) - 3): current_cells *= 2 cells_by_level.append(current_cells) return cells_by_level def index_1d_from_2d(self, level, cell): if level >= self.num_levels: raise Exception("level greater than maze levels") idx = 0 for lvl in range(level): idx += self.num_cells_at_level[lvl] idx += cell return idx def index_2d_from_1d(self, idx): if idx >= self.total_cells: raise Exception("1D index greater than total number of cells") level = 0 while idx - self.num_cells_at_level[level] >= 0: idx -= self.num_cells_at_level[level] level += 1 return level, idx def parent_index_1d(self, level, cell): if level <= 0: raise Exception(f'Level {level} has no parent') elif level == 1: return 0 parent_level = level - 1 if self.num_cells_at_level[parent_level] < self.num_cells_at_level[level]: # 子层级单元格数量翻倍,父单元格为cell//2 parent_cell = cell // 2 else: # 单元格数量相同,父单元格同索引 parent_cell = cell return self.index_1d_from_2d(parent_level, parent_cell) def left_index_1d(self, level, cell): if level <= 0: raise Exception(f'Level {level} has no left cell') left_cell = cell - 1 if cell > 0 else self.num_cells_at_level[level] - 1 return self.index_1d_from_2d(level, left_cell) def right_index_1d(self, level, cell): if level <= 0: raise Exception(f'Level {level} has no right cell') right_cell = cell + 1 if cell < self.num_cells_at_level[level] - 1 else 0 return self.index_1d_from_2d(level, right_cell) def create_dfs_tree(self): print("Creating DFS tree...") graph = {node: [] for node in range(self.total_cells)} # 从非中心单元格开始,避免DFS过早陷入中心 start_cell = random.randint(1, self.total_cells - 1) visited = [start_cell] stack = deque([start_cell]) total_cells_visited = 1 while len(visited) < self.total_cells: cell_1d = stack[-1] level, cell = self.index_2d_from_1d(cell_1d) connections = [] if level == 0: # 中心单元格连接所有level 1的单元格 for c in range(self.num_cells_at_level[1]): connections.append(self.index_1d_from_2d(1, c)) else: # 添加父单元格连接 connections.append(self.parent_index_1d(level, cell)) # 添加左右邻居连接 connections.append(self.left_index_1d(level, cell)) connections.append(self.right_index_1d(level, cell)) # 添加子单元格连接(如果不是最外层) if level < self.num_levels - 1: if self.num_cells_at_level[level] < self.num_cells_at_level[level + 1]: # 当前层级单元格少,子层级翻倍,添加两个子单元格 connections.append(self.index_1d_from_2d(level + 1, 2 * cell)) connections.append(self.index_1d_from_2d(level + 1, 2 * cell + 1)) else: # 单元格数量相同,添加对应子单元格 connections.append(self.index_1d_from_2d(level + 1, cell)) # 筛选未访问的连接 unvisited_connections = [conn for conn in connections if conn not in visited] if unvisited_connections: next_cell = random.choice(unvisited_connections) graph[cell_1d].append(next_cell) graph[next_cell].append(cell_1d) visited.append(next_cell) total_cells_visited += 1 stack.append(next_cell) else: stack.pop() if total_cells_visited % 100 == 0: print(f"Generating DFS Tree: {((total_cells_visited / self.total_cells) * 100):.2f}%") print("DFS tree created") return graph def draw_maze(self, graph): print("Drawing maze...") image = Image.new("RGB", (self.canvas_size, self.canvas_size), "white") draw = ImageDraw.Draw(image) center_x = self.canvas_size // 2 center_y = self.canvas_size // 2 level_width = self.line_length + self.corridor_size # 绘制中心区域(level 0)的外围圆弧 level_0_radius = level_width draw.arc( [center_x - level_0_radius, center_y - level_0_radius, center_x + level_0_radius, center_y + level_0_radius], start=0, end=360, fill="black", width=self.wall_width ) for level in range(1, self.num_levels): current_radius = level * level_width num_cells = self.num_cells_at_level[level] arc_angle = 360.0 / num_cells parent_level = level - 1 parent_radius = parent_level * level_width for cell in range(num_cells): cell_1d = self.index_1d_from_2d(level, cell) parent_cell_1d = self.parent_index_1d(level, cell) right_cell_1d = self.right_index_1d(level, cell) # 绘制右侧分隔墙(替换左侧墙,避免重复绘制) if right_cell_1d not in graph[cell_1d]: start_angle = cell * arc_angle end_angle = start_angle + arc_angle / 2 draw.arc( [center_x - current_radius, center_y - current_radius, center_x + current_radius, center_y + current_radius], start=start_angle, end=end_angle, fill="black", width=self.wall_width ) # 绘制到父层级的径向墙 if parent_cell_1d not in graph[cell_1d]: # 计算角度:子单元格中心角度,确保对齐父单元格范围 angle_rad = math.radians(cell * arc_angle + arc_angle / 2) # 当前层级的端点 x1 = center_x + current_radius * math.cos(angle_rad) y1 = center_y + current_radius * math.sin(angle_rad) # 父层级的端点 x2 = center_x + parent_radius * math.cos(angle_rad) y2 = center_y + parent_radius * math.sin(angle_rad) draw.line([x1, y1, x2, y2], fill="black", width=self.wall_width) # 绘制最外层的完整外圆弧 last_level_radius = (self.num_levels - 1) * level_width draw.arc( [center_x - last_level_radius, center_y - last_level_radius, center_x + last_level_radius, center_y + last_level_radius], start=0, end=360, fill="black", width=self.wall_width ) image.save("maze.png") image.show() # 参数配置 levels = 15 # end goal 70 & 100 line_len = 15 # end goal 70 & 100 wall_width = 8 # end goal 8 & 12 corridor_size = 25 # end goal 25 & 50 canvas_size = 2048 # end goal 16384 maze = CircularMaze(levels, line_len, wall_width, corridor_size, canvas_size) graph = maze.create_dfs_tree() maze.draw_maze(graph)
关键修改说明
- 单元格数量计算优化:
cell_count_by_level方法调整为按2的幂次层级翻倍,确保单元格数量变化仅为1倍或2倍,简化角度对齐逻辑 - 边界圆弧补充:新增中心区域外围圆弧和最外层外圆弧绘制,闭合迷宫边界
- 径向墙长度修正:径向墙从当前层级半径延伸到上一层级半径,覆盖完整层级宽度
- 分隔墙绘制优化:将左侧墙改为右侧墙绘制,避免重复绘制同一墙体
- 角度计算精度提升:统一使用弧度计算角度,减少浮点误差,确保层级衔接时的位置精准
内容的提问来源于stack exchange,提问作者asdf
相关产品推荐
相关产品推荐

