Рекурсия треугольника Серпинского с использованием черепашьей графики

Я пытаюсь написать программу, которая рисует дерево серпинского с помощью 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)

Программа не достигает 2-й строки после оператора else, и я не знаю, почему. Может кто-нибудь помочь мне?


person AlexConfused    schedule 10.09.2014    source источник


Ответы (6)


Я не думаю, что вам следует создавать объект черепахи или окна внутри функции. Поскольку 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()

Результат:

введите здесь описание изображения


Эти результаты выглядят довольно хорошо для треугольника глубины 1, но что если мы вызовем draw_sierpinski(100,2)?

введите здесь описание изображения

Ох, не так хорошо. Это происходит потому, что функция должна нарисовать фигуру, а затем вернуть черепаху в исходное начальное положение и угол. Но, как видно из изображения глубины 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()

Результат:

введите здесь описание изображения

person Kevin    schedule 10.09.2014
comment
Спасибо. Я немного запутался в сложном решении... Похоже, что функция просто использует t, но мы не передали его функции в качестве параметра. Разве это не странно? - person AlexConfused; 10.09.2014
comment
t в данном случае фактически является глобальной переменной. Он должен быть виден любой функции, созданной в файле. - person Kevin; 10.09.2014

Ну вот.

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()
person Navneet Sinha    schedule 28.02.2016

Это лучший код для треугольника Серпинского

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()
person lisi    schedule 07.12.2016

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

Я посмотрел на похожую программу и написал ее, используя некоторые из тех же вещей. Это даст вам самый большой треугольник, который вы можете получить. Надеюсь это поможет!

person HW00D    schedule 30.04.2017

В качестве предложения вот мое решение. Любые комментарии очень ценятся, так как кажется, что это все еще не самый эффективный алгоритм.

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()
person Nicko    schedule 17.08.2018

начиная с Навнит Синха, я бы предложил следующее:

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()    
person andrea    schedule 14.11.2019