使用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时,矩形尺寸偏离预期,且所有矩形都会被分割,不符合“仅分割每次生成的较大矩形”的要求
问题根源
- 全局变量干扰:
count和posTest是全局变量,递归的所有分支会共享这些状态,导致分割方向、海龟位置的逻辑混乱。 - 递归逻辑错误:当前代码会对所有子矩形进行递归分割,而非仅针对每次生成的较大矩形。
- 位置管理失效:依赖海龟移动的位置控制逻辑,在多层递归下无法精准跟踪每个矩形的绘制起点,导致坐标偏移。
修复方案
核心调整方向
- 移除全局变量,改用参数传递递归所需的所有状态(位置、尺寸、分割方向、层级)
- 每次递归仅对较大的子矩形进行下一层分割,小矩形直接绘制
- 用绝对坐标定位矩形左上角,替代海龟移动的位置控制逻辑,避免偏移
修复后的代码
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
相关产品推荐
相关产品推荐

