如何让海龟一起移动?
这是我的代码(我是Python初学者,请多包涵我代码中的不专业之处),我基本上想让两个小海龟一起在同一个圆圈里移动(你可能猜到,我的任务是模拟一艘宇宙飞船追逐国际空间站)。在我的代码中,第一个小海龟会先在圆圈上移动,然后第二个小海龟:
from turtle import *
rocket=Turtle()
ISS=Turtle()
counter=1
title("ISS")
screensize(750,750)
ISS.hideturtle()
rocket.hideturtle()
ISS.penup()
ISS.left(90)
ISS.fd(250)
ISS.left(90)
ISS.showturtle()
ISS.pendown()
rocket.penup()
rocket.fd(250)
rocket.left(90)
rocket.showturtle()
rocket.pendown()
while counter==1:
ISS.speed(1)
rocket.speed(2)
ISS.circle(250)
rocket.circle(250)
我的老师告诉我“线程(threading)”可以解决这个问题,但我不是很明白这个意思。如果有人能帮我一下,我会非常感激;)
2 个回答
0
在像turtle这样的事件驱动环境中,你不应该这样做:
counter = 1
...
while counter==1:
这样做可能会导致事件无法响应。而且,这样的程序没有办法干净利落地退出。与其在一个while
循环中移动不同的距离,不如在ontimer()
事件中移动一个固定的距离,但设置不同的延迟(这个方法在Python 2和3中都可以用):
from turtle import Turtle, Screen
RADIUS = 250
ISS_DELAY = 100 # milliseconds
ROCKET_DELAY = 75 # milliseconds
CURSOR_SIZE = 20
def move_ISS():
ISS.circle(RADIUS, 1)
screen.ontimer(move_ISS, ISS_DELAY)
def move_rocket():
rocket.circle(RADIUS, 1)
# rocket slows to ISS' speed once docked
delay = ISS_DELAY if rocket.distance(ISS) <= CURSOR_SIZE else ROCKET_DELAY
screen.ontimer(move_rocket, delay)
screen = Screen()
screen.title("ISS")
screen.setup(750, 750)
ISS = Turtle("square", visible=False)
ISS.speed('fastest')
ISS.penup()
ISS.left(180)
ISS.sety(RADIUS)
ISS.showturtle()
ISS.pendown()
rocket = Turtle("triangle", visible=False)
rocket.speed('fastest')
rocket.penup()
rocket.left(90)
rocket.setx(RADIUS)
rocket.showturtle()
rocket.pendown()
move_ISS()
move_rocket()
screen.exitonclick()
你可以在窗口的任何地方随时点击,以干净利落地退出程序,这样可以确保事件处理正常。而且我还加了一些逻辑,让宇宙飞船在与国际空间站对接后能够停留在那里,而不是飞过去。
这也可以通过线程来实现,但所有的图形操作必须通过主线程来进行,以避免Tkinter错误(这是一个仅适用于Python3的解决方案):
from threading import Thread, active_count
from turtle import Turtle, Screen
from queue import Queue # use for thread-safe communications
from time import sleep
RADIUS = 250
ISS_DISTANCE = 3
ROCKET_DISTANCE = 4
CURSOR_SIZE = 20
QUEUE_SIZE = 1
def move_ISS(turtle):
while True:
actions.put((turtle.circle, RADIUS, ISS_DISTANCE))
sleep(0.1)
def move_rocket(turtle):
while True:
# rocket slows to ISS' speed once docked
distance = ISS_DISTANCE if rocket.distance(ISS) <= CURSOR_SIZE else ROCKET_DISTANCE
actions.put((turtle.circle, RADIUS, distance))
sleep(0.1)
def process_queue():
while not actions.empty():
action, *arguments = actions.get()
action(*arguments)
if active_count() > 1:
screen.ontimer(process_queue, 100)
actions = Queue(QUEUE_SIZE)
screen = Screen()
screen.title("ISS")
screen.setup(750, 750)
ISS = Turtle("square", visible=False)
ISS.speed('fastest')
ISS.penup()
ISS.left(180)
ISS.sety(RADIUS)
ISS.showturtle()
ISS.pendown()
ISS_thread = Thread(target=move_ISS, args=[ISS], daemon=True)
rocket = Turtle("triangle", visible=False)
rocket.speed('fastest')
rocket.penup()
rocket.left(90)
rocket.setx(RADIUS)
rocket.showturtle()
rocket.pendown()
rocket_thread = Thread(target=move_rocket, args=[rocket], daemon=True)
ISS_thread.start()
rocket_thread.start()
process_queue()
screen.exitonclick()
1
有一个关于海龟的限制,让它不能在多线程中工作。
不过,你不需要让海龟在整个圆圈里转,你可以只让它转一部分。而且,我觉得你可能误解了speed
的意思。它只是指海龟绘图的速度。
from turtle import *
def move(thing, distance):
thing.circle(250, distance)
def main():
rocket = Turtle()
ISS = Turtle()
rocket.speed(10)
ISS.speed(10)
counter = 1
title("ISS")
screensize(750, 750)
ISS.hideturtle()
rocket.hideturtle()
ISS.penup()
ISS.left(90)
ISS.fd(250)
ISS.left(90)
ISS.showturtle()
ISS.pendown()
rocket.penup()
rocket.fd(250)
rocket.left(90)
rocket.showturtle()
rocket.pendown()
while counter == 1:
move(ISS, 3)
move(rocket, 4)
if __name__ == '__main__':
main()
我把移动物体(无论是国际空间站还是火箭)的重复步骤去掉了,把它做成了一个函数。我把绘图的速度调到了10,因为我觉得这样看起来更流畅。现在,国际空间站每一步移动的距离只有火箭的3/4。