Странная L-система в графике черепахи-питона

Я попытался использовать модуль черепах в Python 3, чтобы воссоздать фрактал, найденный здесь: https://en.wikipedia.org/wiki/L-system#Example_7:_Fractal_plant, но всякий раз, когда я пытаюсь это сделать, я получаю очень странный результат...

Вот мой код:

import turtle
wn = turtle.Screen()
wn.bgcolor("white")
wn.screensize(10000, 10000)

tess = turtle.Turtle()
tess.color("lightgreen")
tess.pensize(1)
tess.speed(0)
tess.degrees()

inst = 'X'
steps = 3

for counter in range(steps):
    _inst = ''
    for chtr in inst:
        if chtr == 'X':
            _inst += 'F−[[X]+X]+F[+FX]−X'
        elif chtr == 'F':
            _inst += 'FF'
        else:
            _inst += chtr
    inst = _inst
    print(inst)


for chtr in inst:
    if (chtr == 'F'):
        tess.forward(25)
    elif (chtr == '+'):
        tess.right(25)
    elif (chtr == '-'):
        tess.left(25)
    elif (chtr == '['):
        angle = tess.heading()
        pos = [tess.xcor(), tess.ycor()]
    elif (chtr == ']'):
        tess.setheading(angle)
        tess.penup()
        tess.goto(pos[0], pos[1])
        tess.pendown()
wn.exitonclick()

Я трижды все перепроверил и у меня вроде нет багов - но все равно не работает. Что я делаю ужасно неправильно?

Заранее благодарю за любую помощь!


person Vladimir Shevyakov    schedule 26.03.2016    source источник


Ответы (2)


В вашем коде есть две проблемы.

Во-первых, ваш код неправильно обрабатывает вложенные скобки. Внутренняя открывающая скобка сохраняет свое состояние поверх предыдущего состояния, сохраненного, когда была видна внешняя открывающая скобка. Это не будет иметь значения для непосредственно вложенных скобок, таких как [[X]+X] (поскольку обе они имеют одинаковое начальное состояние), но как только вы усложните вложение (что произойдет после нескольких циклов подстановки), проблема начнет приводить к тому, что все пойдет не так.

Чтобы решить эту проблему, вы, вероятно, захотите сохранить сохраненные значения состояния в стеке (это может сделать list). Нажмите значения, которые вы хотите сохранить, и извлеките их обратно, когда будете готовы их восстановить.

stack = [] # use a list for the stack
for chtr in inst:
    if (chtr == 'F'):
        tess.forward(25)
    elif (chtr == '+'):
        tess.right(25)
    elif (chtr == '-'):
        tess.left(25)
    elif (chtr == '['):
        angle = tess.heading()
        pos = [tess.xcor(), tess.ycor()]
        stack.append((angle, pos)) # push state to save
    elif (chtr == ']'):
        angle, pos = stack.pop()  # pop state to restore
        tess.setheading(angle)
        tess.penup()
        tess.goto(pos[0], pos[1])
        tess.pendown()

Второй вопрос более банален. Ваш синтаксический анализатор ищет символ "минус" (-). Но ваш код генерации шаблонов использует другой, немного более длинный вид тире (). Измените один из них, чтобы он совпадал с другим (на самом деле не имеет значения, какой именно), и ваш код будет работать так, как ожидалось.

person Blckknght    schedule 26.03.2016
comment
@Blcknght, спасибо! По какой-то причине в вики сказано, что [ означает сохранить текущий угол и положение, перекрывая все предыдущие сохранения. Но работает сейчас! - person Vladimir Shevyakov; 26.03.2016

Согласно странице Википедии, символ '[' означает сохранение текущего состояния (угол и позиции). Соответствие ']' означает восстановление ранее сохраненной позиции. Поскольку '[' и ']' могут быть вложенными, необходим стек.

from collections import deque

...

stack = deque()

for chtr in inst:
    if (chtr == 'F'):
        tess.forward(25)

    elif (chtr == '+'):
        tess.right(25)

    elif (chtr == '-'):
        tess.left(25)

    elif (chtr == '['):
        angle = tess.heading()
        pos = [tess.xcor(), tess.ycor()]
        stack.append((angle, pos))         ### New statement

    elif (chtr == ']'):
        angle, pos = stack.pop()           ### New statement
        tess.setheading(angle)
        tess.penup()
        tess.goto(pos[0], pos[1])
        tess.pendown()

. . .
person RootTwo    schedule 26.03.2016