Python 使用海龟图形的谢尔宾斯基三角递归
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 
原文地址: http://stackoverflow.com/questions/25772750/
Warning: these are provided under cc-by-sa 4.0 license.  You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sierpinski triangle recursion using turtle graphics
提问by AlexConfused
I am trying to write a program that draws a sierpinski tree with python using turtle. Here is my idea:
我正在尝试编写一个程序,该程序使用乌龟用 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)
The program does not reach the 2nd line after the else statement and I don't know why. Can anyone help me?
程序没有到达 else 语句之后的第二行,我不知道为什么。谁能帮我?
采纳答案by Kevin
I don't think you should be creating the turtle or window object inside the function. Since draw_sierpinskigets called four times if you originally call it with depth 1, then you'll create four separate windows with four separate turtles, each one drawing only a single triangle. Instead, I think you should have only one window and one turtle.
我认为您不应该在函数内部创建乌龟或窗口对象。由于draw_sierpinski如果您最初使用深度 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)
window = turtle.Screen()
t = turtle.Turtle()
draw_sierpinski(500,1)
window.exitonclick()
Result:
结果:


These results look pretty good for a depth 1 triangle, but what about when we call draw_sierpinski(100,2)?
对于深度为 1 的三角形,这些结果看起来不错,但是当我们调用 时draw_sierpinski(100,2)呢?


Ooh, not so good. This occurs because the function should draw the shape, and then return the turtle to its original starting position and angle. But as is evident from the depth 1 image, the turtle doesn't return to its starting position; it ends up halfway up the left slope. You need some additional logic to send it back home.
哦,不太好。发生这种情况是因为函数应该绘制形状,然后将海龟返回到其原始起始位置和角度。但是从深度 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()
Result:
结果:


回答by Navneet Sinha
Here you go.
干得好。
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()
回答by lisi
This is the best code for sierpinski triangle
这是谢尔宾斯基三角形的最佳代码
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()
回答by HW00D
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()
I looked at a similar program and wrote this using some of the same things. This will give you the biggest triangle that you can get. Hope this helps!
我查看了一个类似的程序,并使用一些相同的东西编写了这个程序。这将为您提供最大的三角形。希望这可以帮助!
回答by Nicko
As a suggestion here is my solution. Any comments are very much appreciated as it seems like it is still not the most efficient algorithm.
作为建议,这是我的解决方案。任何评论都非常感谢,因为它似乎仍然不是最有效的算法。
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()
回答by Kenneth Chang
# 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()
回答by andrea
starting from Navneet Sinha, i would suggest this:
从 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()    

