You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PIL生成环形迷宫的问题排查与解决请求

环形迷宫生成程序问题修复

问题1:墙体线条不完整、长度不足

问题原因

  • 未绘制中心区域(level 0)的外围圆弧和最外层的完整外圆弧
  • 径向墙仅绘制了line_length长度,未覆盖整个层级的径向宽度(line_length + corridor_size)
  • 左侧墙体重复绘制,部分边界未闭合

修复方案

  1. 补充中心区域外围圆弧和最外层外圆弧,确保迷宫边界完整
  2. 修正径向墙的终点坐标,使其连接到上一层级的半径,覆盖完整层级宽度
  3. 调整墙体绘制逻辑,避免重复绘制分隔墙

问题2:层级单元格数量变化时衔接偏差

问题原因

  • 单元格数量翻倍时,子层级径向墙的角度未与父层级的单元格边界精准对齐
  • 角度计算未考虑层级间单元格数量的比例关系,导致视觉偏差

修复方案

  1. 优化单元格数量计算逻辑,确保层级间数量变化仅为1倍或2倍,保持角度比例一致
  2. 调整径向墙的角度计算,使其严格对齐父层级的单元格角度范围
  3. 统一使用弧度计算角度,减少浮点误差

修改后的完整代码

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)

关键修改说明

  1. 单元格数量计算优化:cell_count_by_level方法调整为按2的幂次层级翻倍,确保单元格数量变化仅为1倍或2倍,简化角度对齐逻辑
  2. 边界圆弧补充:新增中心区域外围圆弧和最外层外圆弧绘制,闭合迷宫边界
  3. 径向墙长度修正:径向墙从当前层级半径延伸到上一层级半径,覆盖完整层级宽度
  4. 分隔墙绘制优化:将左侧墙改为右侧墙绘制,避免重复绘制同一墙体
  5. 角度计算精度提升:统一使用弧度计算角度,减少浮点误差,确保层级衔接时的位置精准

内容的提问来源于stack exchange,提问作者asdf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 00:23:14