使用 L 系统和 Python 海龟生成树

Tree generation using L-systems and Python turtle

我正在尝试使用 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)

我在海龟身上发现了一个奇怪的纹理图案 window:

我怎样才能得到想要的结果?

您的 += 操作将生产规则的应用附加到字符串,但想法是 每次出现的 "F" 字符替换为生产规则的结果。

您可以使用 string#replace, which replaces every occurrence of a substring. You used this before your edit, but didn't assign the return value of the function back to the original sentence variable (replace doesn't work in-place 执行此操作,字符串是不可变的)。

无论哪种方式,额外的内部循环都是不必要的。

另一个重点:生产规则是递归的,因此单个 location 变量不足以存储 "remember" 可能已执行的推送序列。

为了详细说明,这是在多次迭代中应用生产规则后的 sentence 变量的摘录:

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

很明显,在遇到 ] 之前,这有两个连续的 [ 操作。这种嵌套可以任意深。 stack 数据结构是跟踪嵌套、递归位置的最佳方式(location 只能跟踪最后一个,当两个推送操作连续发生时,状态将被破坏)。

每当遇到 [ 操作时,将堆栈上的位置压入(在 Python 中表示为仅使用 append(用于压入)和 pop 没有任何参数来删除列表的后面)。每当遇到 ] 操作时,弹出堆栈并将海龟的位置设置为该位置。

次要的一点是,将硬编码值保留在代码之外是个好主意;将所有 settings/config 变量分组在块的顶部。如果您使用的是函数,请设置这些参数。

这是一个工作版本:

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