【问题标题】:Tree generation using L-systems and Python turtle使用 L-systems 和 Python turtle 生成树
【发布时间】:2020-05-09 01:21:36
【问题描述】:

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

我在海龟窗口中得到一个奇怪的纹理图案:

我怎样才能产生想要的结果?

【问题讨论】:

  • >>> generate(3), 3 是字符串的长度,也就是树的复杂度
  • 好的,当我运行时,我看不到你的视觉效果。我在控制台上收到“F”垃圾邮件,然后窗口立即关闭。你能发布你用来生成你发布的图像的确切代码吗?我可以肯定地说,sentence.replace 没有做你认为它做的事情——它用第二个参数替换了 每一次出现 的第一个参数并且它没有做到这一点。除此之外,我不确定您要实现什么目标。
  • 我在if i == "F"语句中犯了一个小错误,把sentence.replace(i, "FF+[+FFF]-[-F+F+F]")换成句子+= "FF+[+FFF]-[-F+F+F]"
  • 我认为这也不是你想要的。请编辑您的帖子以提供这些更新。
  • 好的,我编辑了它,我将如何改进我的代码以获得预期的结果?

标签: python turtle-graphics l-systems


【解决方案1】:

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

您可以使用string#replace 来执行此操作,它会替换每个出现的子字符串。您在编辑之前使用了它,但没有将函数的返回值分配回原始的 sentence 变量(replace 不起作用 in-place 并且字符串是不可变的)。

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

另一个重要的一点:生产规则是递归的,所以单个location 变量不足以“记住”可能已经执行的推送序列。

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

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

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

每当遇到[ 操作时,将位置推入堆栈(在Python 中表示为仅使用append(用于推入)和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()

【讨论】:

    猜你喜欢
    • 2013-02-22
    • 1970-01-01
    • 2017-07-04
    • 2015-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多