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

使用Turtle与递归实现蒙德里安风格图案的代码异常排查

蒙德里安递归图案绘制问题排查与修复

问题背景

作业要求生成皮特·蒙德里安风格的递归抽象图案:从随机颜色填充的矩形开始,反复将当前的较大矩形分割为1/3和2/3面积的两个不等子矩形并填充随机颜色,交替横竖分割方向,直至达到指定递归层级。

当前代码

from turtle import Turtle, tracer, update
from random import randint

count = 0
posTest = 0
def draw(t, length, width, step, level):
    global count, posTest
    
    if level == 0:#base case
        t.fillcolor(randint(0,255),randint(0,255),randint(0,255))
        t.begin_fill()
        #being calculations
        t.forward(step)
        t.forward(length)
        t.right(90)
        t.forward(width)
        t.right(90)
        t.forward(length)
        t.right(90)
        t.forward(width)
        t.right(90)
        
        t.end_fill()
        if posTest % 2 == 1:#if it's 2nd box, move to pos for next iteration
            t.forward(length)
            t.right(90)#length becomes width here
            
        posTest += 1

    else: # two calls for 2 more rectangles
        if count % 2 == 0:
            draw(t, length*(1/3), width, 0, level-1)
            draw(t, length*(2/3), width, length*(1/3), level-1)
            count += 1
        else:
            draw(t, width*(1/3), length, 0, level-1)#flip width and height
            draw(t, width*(2/3), length, width*(1/3), level-1)
            count += 1
            

def main():
    t = Turtle()
    #tracer(False)
    #grid.draw_grid(10,-200,200,-100,100)
    update()
    length = 400
    width = length//2
    level = 2
    step = 0
    t.up()
    t.goto(-.5*length,.5*width)
    t.down()
    draw(t,length,width, step, level)

if __name__ == "__main__":
    main()

问题现象

  • level=0、1时输出正常
  • level≥2时,矩形尺寸偏离预期,且所有矩形都会被分割,不符合“仅分割每次生成的较大矩形”的要求

问题根源

  1. 全局变量干扰:count和posTest是全局变量,递归的所有分支会共享这些状态,导致分割方向、海龟位置的逻辑混乱。
  2. 递归逻辑错误:当前代码会对所有子矩形进行递归分割,而非仅针对每次生成的较大矩形。
  3. 位置管理失效:依赖海龟移动的位置控制逻辑,在多层递归下无法精准跟踪每个矩形的绘制起点,导致坐标偏移。

修复方案

核心调整方向

  • 移除全局变量,改用参数传递递归所需的所有状态(位置、尺寸、分割方向、层级)
  • 每次递归仅对较大的子矩形进行下一层分割,小矩形直接绘制
  • 用绝对坐标定位矩形左上角,替代海龟移动的位置控制逻辑,避免偏移

修复后的代码

from turtle import Turtle, tracer, update
from random import randint

def draw_mondrian(t, x, y, width, height, level, split_horizontal):
    # 填充随机RGB颜色
    t.fillcolor(randint(0, 255), randint(0, 255), randint(0, 255))
    t.begin_fill()
    # 绘制当前矩形(通过绝对坐标定位)
    t.penup()
    t.goto(x, y)
    t.pendown()
    t.goto(x + width, y)
    t.goto(x + width, y - height)
    t.goto(x, y - height)
    t.goto(x, y)
    t.end_fill()

    if level == 0:
        return

    if split_horizontal:
        # 横向分割:按宽度分1/3和2/3,仅递归较大的右侧矩形,切换分割方向
        split_width = width * (1/3)
        draw_mondrian(t, x + split_width, y, width - split_width, height, level - 1, not split_horizontal)
    else:
        # 纵向分割:按高度分1/3和2/3,仅递归较大的下侧矩形,切换分割方向
        split_height = height * (1/3)
        draw_mondrian(t, x, y - split_height, width, height - split_height, level - 1, not split_horizontal)

def main():
    t = Turtle()
    t.speed(0)
    tracer(False)  # 关闭实时绘制,提升多层递归的绘制效率
    # 初始矩形参数:中心在原点,宽400,高200
    initial_width = 400
    initial_height = initial_width // 2
    start_x = -initial_width / 2
    start_y = initial_height / 2
    # 初始分割方向设为横向,可根据需求调整
    draw_mondrian(t, start_x, start_y, initial_width, initial_height, level=3, split_horizontal=True)
    update()  # 一次性渲染所有图形
    t.hideturtle()
    input("按回车键关闭窗口...")

if __name__ == "__main__":
    main()

代码说明

  • 所有状态通过参数传递,递归分支间互不干扰,避免全局变量导致的逻辑混乱
  • 严格遵循需求:每次仅对较大的子矩形进行递归分割,小矩形直接绘制
  • 用绝对坐标定位每个矩形的左上角,位置控制精准,不会出现偏移
  • 开启tracer(False)提升绘制速度,多层递归时不会出现卡顿

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 16:22:09