Как запустить две черепахи в питоне одновременно?

Я пытаюсь заставить двух черепах двигаться вместе, а не одну за другой. Например:

a = turtle.Turtle()
b = turtle.Turtle()

a.forward(100)
b.forward(100)

Но это только заставляет их двигаться друг за другом. Есть ли способ заставить их двигаться вместе одновременно?


person rasabi    schedule 07.11.2018    source источник
comment
Как определяется класс черепахи? Не могли бы вы предоставить код?   -  person Banghua Zhao    schedule 08.11.2018
comment
В SO вы не должны добавлять [ОТВЕТ] или подобное в заголовок вопроса, вы должны пометить как правильный ответ, который является решением вашей проблемы, если ни один ответ вам не поможет, мы приглашаем вас опубликовать свое решение и отметить его как правильно.   -  person eyllanesc    schedule 16.11.2018


Ответы (2)


Есть ли способ заставить их двигаться вместе одновременно?

Лучшее, на что мы можем надеяться, — заставить их двигаться одновременно. Ниже приведены три все более сложных подхода к этой проблеме. Но сначала давайте установим наш базовый код, две черепахи, направляющиеся друг к другу и останавливающиеся, когда встречаются в начале координат:

from turtle import Screen, Turtle

screen = Screen()

a = Turtle('square', visible=False)
a.speed('slow')
a.color('red')
a.penup()
a.setx(-300)
a.setheading(0)
a.pendown()
a.showturtle()

b = Turtle('circle', visible=False)
b.speed('slow')
b.color('green')
b.penup()
b.setx(300)
b.setheading(180)
b.pendown()
b.showturtle()

### Subsequent variations start here ###

a.forward(300)
b.forward(300)

### Subsequent variations end here ###

screen.mainloop()

Вышеупомянутое не делает то, что мы хотим, когда одна черепаха движется, а затем другая. Для нашего первого варианта мы просто разбиваем движение на более мелкие части и чередуем:

###

for _ in range(300):
    a.forward(1)
    b.forward(1)

###

Наш следующий вариант использует события таймера для управления движением двух черепах:

###

def move(turtle):
    turtle.forward(1)

    if turtle.distance(0, 0) > 1 :
        screen.ontimer(lambda t=turtle: move(t), 50)

move(a)
move(b)

###

Наш последний вариант использует потоки для независимого управления двумя черепахами. Каждая черепаха — это поток, и есть третий, основной поток, который обрабатывает все графические операции для потоков черепахи. Это необходимо, поскольку черепаха работает поверх tkinter, у которого есть проблемы с обработкой графики из вторичных потоков:

###

from threading import Thread, active_count
from queue import Queue

QUEUE_SIZE = 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)  # a thread-safe data structure

def move(turtle):
    while turtle.distance(0, 0) > 1:
        actions.put((turtle.forward, 1))

Thread(target=move, args=[a], daemon=True).start()
Thread(target=move, args=[b], daemon=True).start()

process_queue()

###
person cdlane    schedule 08.11.2018
comment
Спасибо! Поскольку python — довольно простой (но сильный) язык, я стараюсь, чтобы они двигались одновременно. - person rasabi; 16.11.2018

Вы не можете сделать это как гарантированную часть интерфейса Черепахи. Вы можете попробовать сделать это в параллельных процессах, но нет гарантии одновременного перемещения. Некоторые системы времени выполнения Python обрабатывают параллельные процессы с последовательным разделением времени одного процесса. Вы также можете обнаружить, что одно перемещение завершается, пока другой процесс инициализируется. Если вы хотите попробовать более жесткое управление, создайте два процесса, удерживающих блокировку процесса; попросите основную программу снять обе блокировки в критической секции... и вы можете получить что-то близкое к желаемой функциональности.

Если вы пытаетесь сделать что-то настолько зрелое с точки зрения графики, вы можете подумать о более крупном графическом пакете, таком как PyGame.

person Prune    schedule 07.11.2018