Python 多只海龟(看似)同时移动
Python Multiple Turtles Moving (seemingly) Simultaneously
我正在为我的老师测试一些东西,他想看看如果我们模拟同步(我知道它不可能完全同步,这是只是为了 learning/practicing) 多只海龟移动的实验。我尝试过使用多处理、线程等模块,甚至是一些疯狂的愚蠢尝试来计时和延迟(我在高中,我刚刚在 python 中了解到 类 因为我之前的一个问题问我想上周)
因此,在多次失败的尝试之后,我想问是否有人对还可以尝试什么有一些想法,或者有一个方向可以模拟海龟的同时移动
导入海龟
从乌龟导入乌龟
turtle.getscreen().delay(0)
class MyTurtle(Turtle):
def petal(self):
for i in range(90):
self.fd(1)
self.rt(1)
self.rt(90)
for i in range(90):
self.fd(1)
self.rt(1)
def stem(self):
self.pencolor('green')
self.fd(250)
def flowerhead(self):
for i in range(9):
self.pencolor('red')
self.begin_fill()
self.petal()
self.lt(230)
self.end_fill()
def stempetal(self):
self.seth(90)
self.rt(15)
self.fillcolor('green')
self.begin_fill()
self.petal()
self.end_fill()
tony = MyTurtle(shape='turtle')
todd = MyTurtle(shape='turtle')
tina = MyTurtle(shape='turtle')
tiny = MyTurtle(shape='turtle')
tweeny = MyTurtle(shape='turtle')
def flower1():
todd.speed('fastest')
todd.fillcolor('blue')
todd.flowerhead()
todd.seth(270)
todd.stem()
todd.stempetal()
def flower2():
tony.speed('fastest')
tony.setpos(80, -15)
tony.pencolor('green')
tony.goto(0, -200)
tony.fillcolor('purple')
tony.goto(80,-15)
tony.rt(40)
tony.flowerhead()
def flower3():
tina.speed('fastest')
tina.setpos(-80, -15)
tina.pencolor('green')
tina.goto(0, -200)
tina.fillcolor('teal')
tina.goto(-80,-15)
tina.lt(40)
tina.flowerhead()
def flower4():
tiny.speed('fastest')
tiny.setpos(160, -25)
tiny.pencolor('green')
tiny.goto(0, -200)
tiny.fillcolor('black')
tiny.goto(160, -25)
tiny.flowerhead()
def flower5():
tweeny.speed('fastest')
tweeny.setpos(-160, -25)
tweeny.pencolor('green')
tweeny.goto(0, -200)
tweeny.fillcolor('pink')
tweeny.goto(-160,-25)
tweeny.lt(40)
tweeny.flowerhead()
flower2()
tony.hideturtle()
flower4()
tiny.hideturtle()
flower3()
tina.hideturtle()
flower5()
tweeny.hideturtle()
flower1()
todd.hideturtle()
感谢您的宝贵时间
解决方案是disable updating the position of each turtle,然后在计算出新位置后强制更新整个屏幕。
import turtle
# our two turtle instances
first, second = turtle.Turtle(), turtle.Turtle()
first.tracer(False) # disable updating view on screen for this turtle!
second.tracer(False)
# make one move - note this will not appear on screen.
first.forward(50)
second.left(20)
# when you are ready to see the whole screen update
turtle.update()
要执行您想要的操作,您必须从根本上做到 每个 新操作都在 turtle.update()
之前完成。您不能像现在这样将其保持为串行执行 - 换句话说,您不能依次 运行 flower1
,然后 flower2
。
这里有一对海龟会同时在屏幕上生成随机图案的例子:
import turtle
import random
# our two turtle instances
turtles = [turtle.Turtle(), turtle.Turtle()]
for turtle_object in turtles:
turtle_object.tracer(False)
for _ in range(10000): # make ten thousand moves.
for t in turtles:
# list the possible moves available
possible_moves = [t.forward, t.back, t.right, t.left]
# give it a random value
random_value = random.randint(0, 100)
# make a random move
random.choice(possible_moves)(random_value)
# update the whole screen now that the new positions have been calculated
turtle.update()
这里的技巧是要注意每个计算每只海龟的新位置,然后告诉整个屏幕更新,然后你才继续下一步。每一步都必须尽可能细化。
您要求了两个不同的东西,'run faster' 和 'simulate simultaneous movement'。我相信我们可以(分别)做这两件事,但我 不 相信 tracer()
和 update()
是这种情况下的答案,因为它们只是创可贴来掩盖真正的问题。
wants to see how the program below could possibly run faster
如果您希望它 运行 更快,请修复 瓶颈 ,即 petal()
函数。用更快的 turtle 内置 circle()
函数替换它。例如:
def petal(self):
self.circle(-60, 90)
self.rt(90)
self.circle(-60, 90)
这将您的代码速度提高了 25 倍,没有其他更改。
simulate simultaneous movement of the turtles
这可以通过 turtle 自己的 ontimer()
事件处理程序和一些仔细的编程来完成。令人惊讶的是,我们使用您原来的 petal()
逻辑,因为它将图形分解为微小的步骤,我们可以在这些步骤之间切换到另一个定时事件的处理:
from random import randint
from turtle import Turtle, Screen
class MyTurtle(Turtle):
def petals(self, size=30, count=8, speed=100):
if size == 30:
self.begin_fill()
if size > 0: # drawing leading edge of petal
self.fd(3)
self.rt(3)
screen.ontimer(lambda: self.petals(size - 1, count, speed), speed)
return
if size == 0: # switch to other edge of petal
self.rt(90)
if size > -30: # drawing trailing edge of petal
self.fd(3)
self.rt(3)
screen.ontimer(lambda: self.petals(size - 1, count, speed), speed)
return
self.end_fill() # finish this petal
self.lt(230) # prepare for the next petal
if count > 0: # drawing the next petal
screen.ontimer(lambda: self.petals(count=count - 1, speed=speed), speed)
return
self.hideturtle() # finished drawing
def stem(self):
self.pencolor('green')
self.fd(250)
def flowerhead(self):
self.pencolor('red')
self.petals(speed=randint(50, 250))
def flower2():
tony.color('green', 'purple')
tony.penup()
tony.goto(0, -200)
tony.pendown()
tony.showturtle()
tony.goto(80, -15)
tony.rt(40)
tony.flowerhead()
def flower3():
tina.color('green', 'turquoise')
tina.penup()
tina.goto(0, -200)
tina.pendown()
tina.showturtle()
tina.goto(-80, -15)
tina.lt(40)
tina.flowerhead()
def flower5():
tweeny.color('green', 'pink')
tweeny.penup()
tweeny.goto(0, -200)
tweeny.pendown()
tweeny.showturtle()
tweeny.goto(-160, -25)
tweeny.lt(40)
tweeny.flowerhead()
tony = MyTurtle(shape='turtle', visible=False)
tina = MyTurtle(shape='turtle', visible=False)
tweeny = MyTurtle(shape='turtle', visible=False)
screen = Screen()
screen.ontimer(flower2, 100)
screen.ontimer(flower3, 120)
screen.ontimer(flower5, 100)
screen.mainloop()
运行 图片
它不会更快,因为它只是一个模拟。 (好吧,它确实走得快了一点,因为我在 return 中为了速度把花瓣画得稍微粗糙了一点。)如果你仔细观察,你会看到海龟(有意地)以它们自己的速度移动。
我正在为我的老师测试一些东西,他想看看如果我们模拟同步(我知道它不可能完全同步,这是只是为了 learning/practicing) 多只海龟移动的实验。我尝试过使用多处理、线程等模块,甚至是一些疯狂的愚蠢尝试来计时和延迟(我在高中,我刚刚在 python 中了解到 类 因为我之前的一个问题问我想上周) 因此,在多次失败的尝试之后,我想问是否有人对还可以尝试什么有一些想法,或者有一个方向可以模拟海龟的同时移动
导入海龟 从乌龟导入乌龟
turtle.getscreen().delay(0)
class MyTurtle(Turtle):
def petal(self):
for i in range(90):
self.fd(1)
self.rt(1)
self.rt(90)
for i in range(90):
self.fd(1)
self.rt(1)
def stem(self):
self.pencolor('green')
self.fd(250)
def flowerhead(self):
for i in range(9):
self.pencolor('red')
self.begin_fill()
self.petal()
self.lt(230)
self.end_fill()
def stempetal(self):
self.seth(90)
self.rt(15)
self.fillcolor('green')
self.begin_fill()
self.petal()
self.end_fill()
tony = MyTurtle(shape='turtle')
todd = MyTurtle(shape='turtle')
tina = MyTurtle(shape='turtle')
tiny = MyTurtle(shape='turtle')
tweeny = MyTurtle(shape='turtle')
def flower1():
todd.speed('fastest')
todd.fillcolor('blue')
todd.flowerhead()
todd.seth(270)
todd.stem()
todd.stempetal()
def flower2():
tony.speed('fastest')
tony.setpos(80, -15)
tony.pencolor('green')
tony.goto(0, -200)
tony.fillcolor('purple')
tony.goto(80,-15)
tony.rt(40)
tony.flowerhead()
def flower3():
tina.speed('fastest')
tina.setpos(-80, -15)
tina.pencolor('green')
tina.goto(0, -200)
tina.fillcolor('teal')
tina.goto(-80,-15)
tina.lt(40)
tina.flowerhead()
def flower4():
tiny.speed('fastest')
tiny.setpos(160, -25)
tiny.pencolor('green')
tiny.goto(0, -200)
tiny.fillcolor('black')
tiny.goto(160, -25)
tiny.flowerhead()
def flower5():
tweeny.speed('fastest')
tweeny.setpos(-160, -25)
tweeny.pencolor('green')
tweeny.goto(0, -200)
tweeny.fillcolor('pink')
tweeny.goto(-160,-25)
tweeny.lt(40)
tweeny.flowerhead()
flower2()
tony.hideturtle()
flower4()
tiny.hideturtle()
flower3()
tina.hideturtle()
flower5()
tweeny.hideturtle()
flower1()
todd.hideturtle()
感谢您的宝贵时间
解决方案是disable updating the position of each turtle,然后在计算出新位置后强制更新整个屏幕。
import turtle
# our two turtle instances
first, second = turtle.Turtle(), turtle.Turtle()
first.tracer(False) # disable updating view on screen for this turtle!
second.tracer(False)
# make one move - note this will not appear on screen.
first.forward(50)
second.left(20)
# when you are ready to see the whole screen update
turtle.update()
要执行您想要的操作,您必须从根本上做到 每个 新操作都在 turtle.update()
之前完成。您不能像现在这样将其保持为串行执行 - 换句话说,您不能依次 运行 flower1
,然后 flower2
。
这里有一对海龟会同时在屏幕上生成随机图案的例子:
import turtle
import random
# our two turtle instances
turtles = [turtle.Turtle(), turtle.Turtle()]
for turtle_object in turtles:
turtle_object.tracer(False)
for _ in range(10000): # make ten thousand moves.
for t in turtles:
# list the possible moves available
possible_moves = [t.forward, t.back, t.right, t.left]
# give it a random value
random_value = random.randint(0, 100)
# make a random move
random.choice(possible_moves)(random_value)
# update the whole screen now that the new positions have been calculated
turtle.update()
这里的技巧是要注意每个计算每只海龟的新位置,然后告诉整个屏幕更新,然后你才继续下一步。每一步都必须尽可能细化。
您要求了两个不同的东西,'run faster' 和 'simulate simultaneous movement'。我相信我们可以(分别)做这两件事,但我 不 相信 tracer()
和 update()
是这种情况下的答案,因为它们只是创可贴来掩盖真正的问题。
wants to see how the program below could possibly run faster
如果您希望它 运行 更快,请修复 瓶颈 ,即 petal()
函数。用更快的 turtle 内置 circle()
函数替换它。例如:
def petal(self):
self.circle(-60, 90)
self.rt(90)
self.circle(-60, 90)
这将您的代码速度提高了 25 倍,没有其他更改。
simulate simultaneous movement of the turtles
这可以通过 turtle 自己的 ontimer()
事件处理程序和一些仔细的编程来完成。令人惊讶的是,我们使用您原来的 petal()
逻辑,因为它将图形分解为微小的步骤,我们可以在这些步骤之间切换到另一个定时事件的处理:
from random import randint
from turtle import Turtle, Screen
class MyTurtle(Turtle):
def petals(self, size=30, count=8, speed=100):
if size == 30:
self.begin_fill()
if size > 0: # drawing leading edge of petal
self.fd(3)
self.rt(3)
screen.ontimer(lambda: self.petals(size - 1, count, speed), speed)
return
if size == 0: # switch to other edge of petal
self.rt(90)
if size > -30: # drawing trailing edge of petal
self.fd(3)
self.rt(3)
screen.ontimer(lambda: self.petals(size - 1, count, speed), speed)
return
self.end_fill() # finish this petal
self.lt(230) # prepare for the next petal
if count > 0: # drawing the next petal
screen.ontimer(lambda: self.petals(count=count - 1, speed=speed), speed)
return
self.hideturtle() # finished drawing
def stem(self):
self.pencolor('green')
self.fd(250)
def flowerhead(self):
self.pencolor('red')
self.petals(speed=randint(50, 250))
def flower2():
tony.color('green', 'purple')
tony.penup()
tony.goto(0, -200)
tony.pendown()
tony.showturtle()
tony.goto(80, -15)
tony.rt(40)
tony.flowerhead()
def flower3():
tina.color('green', 'turquoise')
tina.penup()
tina.goto(0, -200)
tina.pendown()
tina.showturtle()
tina.goto(-80, -15)
tina.lt(40)
tina.flowerhead()
def flower5():
tweeny.color('green', 'pink')
tweeny.penup()
tweeny.goto(0, -200)
tweeny.pendown()
tweeny.showturtle()
tweeny.goto(-160, -25)
tweeny.lt(40)
tweeny.flowerhead()
tony = MyTurtle(shape='turtle', visible=False)
tina = MyTurtle(shape='turtle', visible=False)
tweeny = MyTurtle(shape='turtle', visible=False)
screen = Screen()
screen.ontimer(flower2, 100)
screen.ontimer(flower3, 120)
screen.ontimer(flower5, 100)
screen.mainloop()
运行 图片
它不会更快,因为它只是一个模拟。 (好吧,它确实走得快了一点,因为我在 return 中为了速度把花瓣画得稍微粗糙了一点。)如果你仔细观察,你会看到海龟(有意地)以它们自己的速度移动。