Как запустить двух черепах в питоне одновременно? - PullRequest
0 голосов
/ 08 ноября 2018

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

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

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

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

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

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

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

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)

###

Наш последний вариант использует потоки для независимого управления двумя черепахами. Каждая черепаха является потоком, и есть третий, основной поток, который обрабатывает все графические операции для потоков черепахи. Это необходимо, так как Turtle работает поверх 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()

###
0 голосов
/ 08 ноября 2018

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

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

...