如何在不无限期克隆的情况下将 Turtle 克隆附加到列表中?
How can I append Turtle clones to a list without cloning indefinitely?
我必须使用 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
首先,你有一个逻辑错误。您的外部循环遍历海龟,然后在循环内,它分别处理 all 每个海龟的步骤。这是不正确的;即使它有效,它也会将 在 拆分之前的指令应用到在它之后创建的海龟上。 (这将有效地将前面的指令应用到同一只海龟两次,并再次执行拆分 。)您需要在所有海龟上一次处理一个步骤。所以循环需要在方向上,而不是海龟上:
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
的末尾。我将把这两个列表结合起来作为你的练习。
奖金Material
这里有一些让您的代码更简洁的建议:
使用解包,这样您就不必到处都有索引。
你其实不需要使用索引来访问step
中的两条数据。您可以使用解包将每个元素放入其自己的变量中:
for action, value in directions:
if action == 'split':
...
else:
...
turt.forward(value)
这使您的代码更加简单易读,尽管您可能会为 value
.
想出更好的名称
您实际上不必使用明确的临时列表和 for
循环来制作克隆。您可以使用列表理解:
turtle_clones = [t.clone() for t in turtles]
同样,更简单易读。
first
变量似乎是不必要的。可以直接初始化包含第一只乌龟的列表:
turtles = [turtle.Turtle()]
我必须使用 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
首先,你有一个逻辑错误。您的外部循环遍历海龟,然后在循环内,它分别处理 all 每个海龟的步骤。这是不正确的;即使它有效,它也会将 在 拆分之前的指令应用到在它之后创建的海龟上。 (这将有效地将前面的指令应用到同一只海龟两次,并再次执行拆分 。)您需要在所有海龟上一次处理一个步骤。所以循环需要在方向上,而不是海龟上:
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
的末尾。我将把这两个列表结合起来作为你的练习。
奖金Material
这里有一些让您的代码更简洁的建议:
使用解包,这样您就不必到处都有索引。
你其实不需要使用索引来访问
step
中的两条数据。您可以使用解包将每个元素放入其自己的变量中:for action, value in directions: if action == 'split': ... else: ... turt.forward(value)
这使您的代码更加简单易读,尽管您可能会为
value
. 想出更好的名称
您实际上不必使用明确的临时列表和
for
循环来制作克隆。您可以使用列表理解:turtle_clones = [t.clone() for t in turtles]
同样,更简单易读。
first
变量似乎是不必要的。可以直接初始化包含第一只乌龟的列表:turtles = [turtle.Turtle()]