使用乌龟和递归函数的Sierpinski三角形

时间:2018-06-02 10:08:55

标签: python recursion turtle-graphics fractals

我试图理解递归函数,它们看起来很复杂。到目前为止,我唯一理解的是他们需要成为一个基础案例,并且它基于归纳证明。程序员如何看待简单的基础案例,直到现在还在思考。仅使用一行基础案例在书中解决了示例分形。在Sierpinski三角形中,我需要这么多行代码。好吧,现在我接近它但仍然遥不可及。下面是适用于订单0和1的代码,但是对于更高的订单,它会增加更多空间。我知道它不是一个pythonic代码,但我能写得最好。

import math, turtle

window=turtle.Screen()
window.title('Sierpinski')
window.bgcolor('lightblue')

alex=turtle.Turtle()

def sierpinski(a,t,size):
    if a==0:
        for i in range(3):
            t.forward(size)
            t.left(120)
    else:
       sierpinski(a-1,t,size/3)
       t.forward(size/3)
       sierpinski(a-1,t,size/3)
       t.forward(size/3)
       t.left(120)
       t.forward(size/3)
       sierpinski(a-1,t,size/3)
       t.forward(size/3)
       t.left(120)
       t.forward(size*2/3)
       t.left(120)

sierpinski(3,alex,200)

window.mainloop()

是的,它有点长,我的思维过程中仍然不清楚

  1. 任何人都可以解释我的代码有什么问题吗?
  2. 如何制作更多的pythonic?

2 个答案:

答案 0 :(得分:1)

好的,我在video的帮助下找到了如何做到这一点,它指示我把它分成两半而不是三分之一。

所以代码应该是

import math, turtle

window=turtle.Screen()
window.title('Sierpinski')
window.bgcolor('lightblue')

alex=turtle.Turtle()

def sierpinski(a,t,size):
    if a==0:
        for i in range(3):
            t.forward(size)
            t.left(120)

    else:
       sierpinski(a-1,t,size/2)
       t.forward(size/2)
       sierpinski(a-1,t,size/2)
       t.forward(size/2)
       t.left(120)
       t.forward(size/2)
       sierpinski(a-1,t,size/2)
       t.forward(size/2)
       t.left(120)
       t.forward(size)
       t.left(120)

sierpinski(3,alex,200)

window.mainloop()

但代码可以更简洁吗?

修改

这就足够了:

def sierpinski(a, t, size):
    half = size / 2
    if a >= 0:
        sierpinski(a-1, t, half)
        t.forward(half)

        sierpinski(a-1, t, half)
        t.forward(half)
        t.left(120)
        t.forward(half)

        sierpinski(a-1, t, half)
        t.forward(half)
        t.left(120)
        t.forward(size)
        t.left(120)

这是有效的,因为if结束else块都是绘制三角形(else块仅用于移动光标,但仍然),但是else块做了递归调用。

要使它成为"更多pythonic" ,你可以将它们全部放入一个类中:

class SierpinskiTurtle(turtle.Turtle):
    def sierpinski(self, depth, size):
        half = size / 2
        if depth >= 0:
            self.sierpinski(depth-1, half)
            self.forward(half)

            self.sierpinski(depth-1, half)
            self.forward(half)
            self.left(120)
            self.forward(half)

            self.sierpinski(depth-1, half)
            self.forward(half)
            self.left(120)
            self.forward(size)
            self.left(120)

alex = SierpinskiTurtle()

alex.sierpinski(3, 200)

答案 1 :(得分:1)

我们可以使用标记而不是绘图使sierpinski()函数更简单,更快捷:

from turtle import Turtle, Screen

CURSOR_SIZE = 20

def sierpinski(depth, turtle, size):

    turtle.shapesize(size / CURSOR_SIZE)
    turtle.stamp()

    if depth < 1:
        return

    half = size / 2
    circumradius = half * 3 ** 0.5 / 3

    for _ in range(3):
        turtle.forward(circumradius)  # to
        sierpinski(depth - 1, turtle, half)
        turtle.backward(circumradius)  # and fro
        turtle.left(120)

window = Screen()
window.mode('logo')  # make 0 degrees straight up
window.title('Sierpinski')
window.bgcolor('lightblue')

alex = Turtle('triangle')
alex.fillcolor(window.bgcolor())
alex.penup()

sierpinski(3, alex, 300)

alex.hideturtle()
window.mainloop()

这也具有将三角形绘制在屏幕上而不是偏向一侧的优点。通过使光标围绕三角形的内径以圆形方式移动而不是围绕中心来回移动,可以进一步优化绘图。