使用乌龟图形的Sierpinski三角递归

时间:2014-09-10 18:41:43

标签: python recursion turtle-graphics

我正在尝试使用turtle编写一个使用python绘制sierpinski树的程序。这是我的想法:

import turtle
def draw_sierpinski(length,depth):
    window = turtle.Screen()
    t = turtle.Turtle()
    if depth==0:
        for i in range(0,3):
            t.fd(length)
            t.left(120)
    else:
        draw_sierpinski(length/2,depth-1)
        t.fd(length/2)
        draw_sierpinski(length/2,depth-1)
        t.bk(length/2)
        t.left(60)
        t.fd(length/2)
        t.right(60)
        draw_sierpinski(length/2,depth-1)
    window.exitonclick()


draw_sierpinski(500,1)

该程序在else语句后没有到达第二行,我不知道为什么。任何人都可以帮助我吗?

7 个答案:

答案 0 :(得分:4)

我认为你不应该在函数中创建乌龟或窗口对象。如果您最初使用深度1调用draw_sierpinski,则import turtle def draw_sierpinski(length,depth): if depth==0: for i in range(0,3): t.fd(length) t.left(120) else: draw_sierpinski(length/2,depth-1) t.fd(length/2) draw_sierpinski(length/2,depth-1) t.bk(length/2) t.left(60) t.fd(length/2) t.right(60) draw_sierpinski(length/2,depth-1) window = turtle.Screen() t = turtle.Turtle() draw_sierpinski(500,1) window.exitonclick() 被调用四次,那么您将创建四个独立的窗口,其中包含四个独立的海龟,每个海龟只绘制一个三角形。相反,我认为你应该只有一个窗口和一只乌龟。

draw_sierpinski(100,2)

结果:

enter image description here


这些结果看起来非常适合深度1三角形,但是当我们调用import turtle def draw_sierpinski(length,depth): if depth==0: for i in range(0,3): t.fd(length) t.left(120) else: draw_sierpinski(length/2,depth-1) t.fd(length/2) draw_sierpinski(length/2,depth-1) t.bk(length/2) t.left(60) t.fd(length/2) t.right(60) draw_sierpinski(length/2,depth-1) t.left(60) t.bk(length/2) t.right(60) window = turtle.Screen() t = turtle.Turtle() draw_sierpinski(100,2) window.exitonclick() 时呢?

enter image description here

哦,不太好。发生这种情况是因为函数应该绘制形状,然后将乌龟返回到其原始起始位置和角度。但从深度1图像可以看出,乌龟并没有回到它的起始位置;它最终在左边坡的一半处。您需要一些额外的逻辑才能将其发回国内。

{{1}}

结果:

enter image description here

答案 1 :(得分:1)

from turtle import *
import turtle
t = turtle.Turtle()
Window = turtle.Screen()

Window.bgcolor('white')

turtle.color('white')
goto(-200, -200)
def serp_tri(side, level):
    if level == 1:
        for i in range(3):
            turtle.color('black')
            turtle.ht()
            turtle.fd(side)
            turtle.left(120)
            turtle.speed(100000)

else:
    turtle.ht()
    serp_tri(side/2, level-1)
    turtle.fd(side/2)
    serp_tri(side/2, level-1)
    turtle.bk(side/2)
    turtle.left(60)
    turtle.fd(side/2)
    turtle.right(60)
    serp_tri(side/2, level-1)
    turtle.left(60)
    turtle.bk(side/2)
    turtle.right(60)
    turtle.speed(100000)

def main():
    serp_tri(400, 8)

if __name__ == '__main__':
    main()
    turtle.mainloop()

我查看了一个类似的程序并使用一些相同的东西写了这个。这将为您提供最大的三角形。希望这可以帮助!

答案 2 :(得分:1)

这是我的建议。非常感谢任何评论,因为它似乎仍然不是最有效的算法。

import turtle

def sier(tur, order, size):
    """ Draw Sierpinski triangle """
    if order == 0:
        for _ in range(3):
            tur.forward(size)
            tur.left(120)
    else:
        step = size / 2
        for t1, m1, t2, m2 in [(0, step, 0, 0),
                               (120, step, -120, 0),
                               (-60, step, 60, -(step))]:
            sier(tur, order - 1, step)
            tur.left(t1)
            tur.forward(m1)
            tur.left(t2)
            tur.forward(m2)


if __name__ == '__main__':
    odr = int(input("Enter the order: "))
    sz = int(input("Enter the size: "))

    root = turtle.Screen()
    root.bgcolor("lightgreen")

    alex = turtle.Turtle()
    alex.color('blue')
    alex.speed(100)

    sier(alex, odr, sz)

    root.mainloop()

答案 3 :(得分:1)

# PEP8 Verified
'''
The Sierpinski function relies heavily on the getMid function. getMid takes
as arguments two endpoints and returns the point halfway between them. In
addition, this program has a function that draws a filled triangle using
the begin_fill and end_fill turtle methods.
'''


import turtle


def drawTriangle(points, color, myTurtle):
    myTurtle.fillcolor(color)
    myTurtle.up()
    myTurtle.goto(points[0][0], points[0][1])
    myTurtle.down()
    myTurtle.begin_fill()
    myTurtle.goto(points[1][0], points[1][1])
    myTurtle.goto(points[2][0], points[2][1])
    myTurtle.goto(points[0][0], points[0][1])
    myTurtle.end_fill()


def getMid(p1, p2):
    return ((p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2)


def sierpinski(points, degree, myTurtle):
    colormap = ['blue', 'red', 'green', 'white', 'yellow', 'violet', 'orange']
    drawTriangle(points, colormap[degree], myTurtle)
    if degree > 0:
        sierpinski([points[0],
                    getMid(points[0], points[1]),
                    getMid(points[0], points[2])],
                   degree-1, myTurtle)
        sierpinski([points[1],
                    getMid(points[0], points[1]),
                    getMid(points[1], points[2])],
                   degree-1, myTurtle)
        sierpinski([points[2],
                    getMid(points[2], points[1]),
                    getMid(points[0], points[2])],
                   degree-1, myTurtle)


def main():
    myTurtle = turtle.Turtle()
    myWin = turtle.Screen()
    myPoints = [[-100, -50], [0, 100], [100, -50]]
    sierpinski(myPoints, 3, myTurtle)
    myWin.exitonclick()

main()

答案 4 :(得分:0)

你走了。

import turtle

def sier(side, level):
    if level == 1:
        for i in range(3):
            turtle.fd(side)
            turtle.left(120)
    else:
        sier(side/2, level-1)
        turtle.fd(side/2)
        sier(side/2, level-1)
        turtle.bk(side/2)
        turtle.left(60)
        turtle.fd(side/2)
        turtle.right(60)
        sier(side/2, level-1)
        turtle.left(60)
        turtle.bk(side/2)
        turtle.right(60)
def main():
    sier(200, 4)

if __name__ == '__main__':
    main()
    turtle.mainloop()

答案 5 :(得分:0)

这是sierpinski三角形的最佳代码

def sierpinski(a, n):
if n == 0:
    t.begin_fill()
    for i in range(3):
        t.fd(a)
        t.lt(120)
    t.end_fill()
    return
sierpinski(a / 2, n - 1)
t.pu()
t.fd(a / 2)
t.pd()
sierpinski(a / 2, n - 1)
t.pu()
t.lt(120)
t.fd(a / 2)
t.rt(120)
t.pd()
sierpinski(a / 2, n - 1)
#
# We should return home! This is important!
#
t.pu()
t.lt(60)
t.bk(a / 2)
t.rt(60)
t.pd()

答案 6 :(得分:0)

从Navneet Sinha开始,我建议这样做:

def sierpinski(t,order,size):
try:
    order=int(order)
    size=float(size)
    if order==0:
        for i in range(0,3):
            t.pendown()             
            t.forward(size)         
            t.left(120)
            t.penup()               
    else:
        for (angle,move) in ([0,size],[60,-size],[-60,-size]):
            sierpinski(t,order-1,size/2)       
            t.right(angle)                              
            t.forward(move/2)                           
            t.left(angle)
except ValueError:
    None

def test_turtle():
    import turtle

    screen=turtle.Canvas()
    tess=turtle.Turtle()
    tess.shape("arrow")
    tess.shapesize(0.2)
    tess.speed(0)

    ords=input("define the order of the fractal: ")
    sz=input("define the size of the segment: ")

    tess.penup()
    tess.backward(float(sz)/2)
    tess.right(90)
    tess.forward(float(sz)/3)
    tess.left(90)
    tess.pendown()

    sierpinski(tess,ords,sz)

    screen.mainloop()

test_turtle()