Генерация деревьев с использованием L-систем и Python черепах - PullRequest
2 голосов
/ 22 января 2020

Я пытаюсь создать простое дерево, используя L-систему. Однако, когда я запускаю код, который у меня есть:

import turtle


def generate(length):
    sentence = "F"
    for j in range(1, length):
        for i in sentence:
            if i == "F":
                sentence += "FF+[+F-F-F]-[-F+F+F]"

        print(sentence)


    gen = turtle.Turtle()
    window = turtle.Screen()
    gen.left(90)

    for k in sentence:
        if k == "F":
            gen.forward(10)
        elif k == "+":
            gen.right(10)
        elif k == "-":
            gen.left(10)
        elif k == "[":
            location = gen.position()
        elif k == "]":
            gen.setposition(location)

, я получаю странный узор зерна в окне черепахи:

turtle window

Как мне получить желаемый результат?

1 Ответ

1 голос
/ 22 января 2020

Ваша операция += добавляет приложение производственного правила к строке, но идея состоит в том, чтобы заменять каждое вхождение символа "F" на результат производственного правила.

Вы можете сделать это с помощью string#replace, который заменяет каждое вхождение подстроки. Вы использовали это перед редактированием, но не присвоили возвращаемое значение функции обратно исходной переменной sentence (replace не работает на месте , и строки являются неизменяемыми).

В любом случае, дополнительный внутренний l oop не нужен.

Еще один важный момент: производственное правило является рекурсивным, поэтому одной переменной location недостаточно места для того, чтобы «запомнить» последовательность толчков, которые могли быть выполнены.

Для уточнения, вот выдержка из вашей переменной sentence после применения производственного правила на нескольких итерациях:

...[-FF+[+F-F-F]-[-F+F+F]+...

Понятно, что перед * есть две последовательные операции [. 1026 * встречается. Это вложение может расти сколь угодно глубоко. Структура данных stack - лучший способ отслеживать вложенные рекурсивные позиции (location может отслеживать только последние и состояние будет повреждено, если две операции pu sh будут выполнены подряд) ,

Всякий раз, когда встречается операция [, pu sh позиция в стеке (представленная в Python как список, который использует только append (для pu sh) и pop без всяких аргументов убрать заднюю часть списка). Всякий раз, когда встречается операция ], вытаскивайте стек и устанавливайте позицию черепахи в это место.

В качестве второстепенной точки зрения, это хорошая идея - не указывать жестко закодированные значения в коде; Сгруппируйте все ваши настройки / настройки в верхней части блока. Если вы используете функцию, задайте эти параметры.

Вот рабочая версия:

import turtle

generations = 3
size = 10
rule = ("F", "FF+[+F-F-F]-[-F+F+F]")
sentence = "F"
positions = []
gen = turtle.Turtle()
gen.speed(10)
gen.left(90)

for i in range(generations):
    sentence = sentence.replace(*rule)

for op in sentence:
    if op == "F":
        gen.forward(size)
    elif op == "+":
        gen.right(size)
    elif op == "-":
        gen.left(size)
    elif op == "[":
        positions.append(gen.position())
    elif op == "]":
        gen.setposition(positions.pop())

turtle.exitonclick()
...