【问题标题】:How can I append Turtle clones to a list without cloning indefinitely?如何在不无限期克隆的情况下将 Turtle 克隆附加到列表中?
【发布时间】:2017-03-25 05:07:54
【问题描述】:

我必须使用 Turtle 在 Python 中编写一个程序,该程序从文件中读取指令列表并根据输入绘制 Turtle 图。可能的输入是向前、向左、向右和拆分。如果输入被拆分,我必须克隆列表中的所有海龟并将新的海龟附加到列表中。所有新的克隆都应该右转 x 度。问题是,海龟无限期地克隆。

def navigate(directions):
    turtles = []
    commands = []
    first = turtle.Turtle()
    turtles.append(first)

    turtle.width(10)

    for turt in turtles:
        turt.speed('fastest')
        for step in directions:
            if step[0] == 'forward':
                turt.forward(step[1])
            elif step[0] == 'left':
                turt.left(step[1])
            elif step[0] == 'right':
                turt.right(step[1])
            elif step[0] == 'split':
                new = turt.clone()
                turtles.append(new)
                turt.right(step[1])

Directions 是一个元组列表,其中每个元组的第一个值是命令(例如向前、向左、向右或拆分),第二个是度数(向前走多远,要转弯多少度)。但是乌龟会永远克隆下去。如何调整此代码以使其仅克隆给定次数?这是我的示例输入文件:

forward 50
left 20
split 40
forward 50
left 20
split 40
forward 50
left 20
split 40
forward 50
left 20
split 40
forward 50
left 20

【问题讨论】:

    标签: python-3.x turtle-graphics


    【解决方案1】:

    首先,你有一个逻辑错误。您的外部循环遍历海龟,然后在循环内部,它分别处理每个海龟的所有步骤。这是不正确的;即使它有效,它也会将分割之前的指令应用到分割之后的海龟上。 (这将有效地将前面的指令两次应用于同一个海龟,并再次执行拆分。)您需要在所有海龟上一次处理一个步骤。所以循环需要越过方向,而不是海龟:

    for step in directions:
        # Process the step
    

    现在我们已经交换了循环,解决方案变得更加明显。对于'split'的情况,我们可以检查步骤并进行特殊处理:

    for step in directions:
        if step[0] == 'split':
            # Clone all the turtles here
        else:
            for turt in turtles:
                if step[0] == 'forward':
                    turt.forward(step[1])
                elif step[0] == 'left':
                ...
    

    我选择为移动案例使用单个循环,但如果您愿意,为每个案例设置一个循环同样有效。

    我们仍然有创建克隆并将它们添加到列表中的问题。您已经看到这不会工作:

    for turt in turtles:
        turtles.append(turt.clone())
    

    所以我们需要存储所有这些新的克隆而不修改我们循环的列表。我们可以使用临时列表来做到这一点:

    turtle_clones = []
    for turt in turtles:
        turtle_clones.append(turt.clone())
    

    然后我们只需要将turtle_clones 放在turtles 的末尾。我将把这两个列表结合起来作为你的练习。

    奖励材料

    以下是一些让您的代码更简洁的建议:

    1. 使用解包,这样您就不必到处都有索引了。

      您实际上不需要使用索引访问step 中的两条数据。您可以使用解包将每个元素放入自己的变量中:

      for action, value in directions:
          if action == 'split':
              ...
          else:
              ...
                  turt.forward(value)
      

      这使您的代码更加简单易读,尽管您可能会为value 想一个更好的名称。

    2. 您实际上不必使用显式临时列表和for 循环来进行克隆。您可以使用列表推导:

      turtle_clones = [t.clone() for t in turtles]
      

      同样,更简单易读。

    3. first 变量似乎没有必要。您可以直接初始化包含第一个海龟的列表:

      turtles = [turtle.Turtle()]
      

    【讨论】:

    • 谢谢!!得到它的工作。我知道循环的嵌套是问题的一部分,但不知道如何解决它。你给了我我需要的一切。
    • @nalydttirrem 识别正确的抽象很容易成为编程中最困难的部分,但随着时间的推移你会变得更好。 =) 以此经验为教训:当事情没有真正落实到位时,这通常表明您对数据或逻辑进行建模的方式不能很好地满足您的需求。
    猜你喜欢
    • 1970-01-01
    • 2017-01-18
    • 2012-07-27
    • 1970-01-01
    • 2013-10-12
    • 1970-01-01
    • 2019-04-29
    • 2020-08-08
    相关资源
    最近更新 更多