使用海龟图形的谢尔宾斯基三角形递归

问题描述 投票:0回答:10

我正在尝试编写一个程序,使用海龟用 python 绘制谢尔宾斯基树。这是我的想法:

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 语句之后的第二行,我不知道为什么。有人可以帮助我吗?

python recursion turtle-graphics
10个回答
11
投票

我认为您不应该在函数内创建海龟或窗口对象。由于如果您最初以深度 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()

结果:

enter image description here


对于深度为 1 的三角形,这些结果看起来相当不错,但是当我们调用

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


3
投票
# 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()

1
投票

给你。

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()

1
投票

这是谢尔宾斯基三角形的最佳代码

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()

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()

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


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()

1
投票

从 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()    

0
投票

代码非常简单:

def sierpinski(size:int,depth:int,up:bool = True):
    if depth==0:
        t.forward(size)
        return
    size = size/2
    depth = depth-1
    left = lambda deg:t.left(deg)
    right = lambda deg:t.right(deg)
    if not up:
        k = left
        left = right
        right = k
        del k
    left(60)
    sierpinski(size,depth,not up)
    right(60)
    sierpinski(size,depth,up)
    right(60)
    sierpinski(size,depth,not up)
    left(60)

0
投票

我来这里寻找Python的答案没有海龟。我想要

PIL
枕头)。解决办法如下:

from PIL import Image, ImageDraw

def midpoint(point1, point2):
    return ((point1[0] + point2[0]) / 2, (point1[1] + point2[1]) / 2)

def draw_triangle(draw, points):
    draw.polygon(points, outline="black")

def sierpinski_triangle(draw, points, degree):
    if degree == 0:
        draw_triangle(draw, points)
    else:
        p1 = midpoint(points[0], points[1])
        p2 = midpoint(points[1], points[2])
        p3 = midpoint(points[0], points[2])

        sierpinski_triangle(draw, [points[0], p1, p3], degree - 1)
        sierpinski_triangle(draw, [p1, points[1], p2], degree - 1)
        sierpinski_triangle(draw, [p3, p2, points[2]], degree - 1)

def main():
    # Set the size of the image
    width, height = 400, 400

    # Create a white image
    image = Image.new("RGB", (width, height), "white")
    draw = ImageDraw.Draw(image)

    # Define the vertices of the initial equilateral triangle
    vertices = [(200, 350), (50, 50), (350, 50)]

    # Set the recursion depth
    recursion_depth = 3

    # Draw the Sierpinski Triangle on the image
    sierpinski_triangle(draw, vertices, recursion_depth)

    # Save or display the image
    image.save("sierpinski_triangle.png")

if __name__ == "__main__":
    main()

-1
投票

我发现一种递归方式来绘制我认为你期望的东西。我的目标实际上是使用数千个点来绘制它,但在我有点伤脑筋之后,我已经解决了这个解决方案:

import turtle
def sierpinski(length, level):
    if level == 0:
        for i in range(3):
            turtle.forward(length)
            turtle.left(120)
    else:
        sierpinski(length/2, level-1)
        turtle.forward(length/2)
        sierpinski(length/2, level-1)
        turtle.backward(length/2)
        turtle.left(60)
        turtle.forward(length/2)
        turtle.right(60)
        sierpinski(length/2, level-1)
        turtle.left(60)
        turtle.backward(length/2)
        turtle.right(60)
turtle.speed(0)
sierpinski(200, 4)
© www.soinside.com 2019 - 2024. All rights reserved.