如何同时启动2功能(龟)(PYTHON)

时间:2016-10-29 19:50:56

标签: python turtle-graphics

我只举一个简单的例子,但我希望我能理解它的逻辑。 例如," 我将如何同时启动两者?"。

感谢您的回答..

@{
    Layout = "~/siteLayout.cshtml";
    Page.Title = "Meta Page";
    Page.MetaKeywords = "keyword1, keyword2, keyword3";
}

你不介意我的剧本,我只想要逻辑。

4 个答案:

答案 0 :(得分:0)

要与其他代码并行启动某些代码,请创建thread

最简单的例子:

my_thread = threading.Thread(target=func1)
my_thread.start()
# start() returns immediately and the thread runs "in backgound"

func2() # runs in the main thread, in parallel with my_thread

my_thread.join() # wait for the thread to finish, if it has not already

编辑:它不起作用

我在发布答案后尝试了这个,不幸的是它不适用于Turtle。我明白了:

  

RuntimeError:主线程不在主循环中

一种不同的方法?

请参阅my other answer

答案 1 :(得分:0)

由于我已经给了bad answer,我现在觉得必须给出更好的一个;)

由于线程不是一个选项,你必须暂停一个函数的执行才能运行另一个函数然后从一个函数切换到另一个函数。

暂停一个函数然后再继续它的一个简单方法是通过产生来生成一个暂停的生成器。

首先,定义用于暂停的地点:

def func1():
    for i in range (4):
        nah.right(45)
        yield
        nah.forward(40)
        yield
        nah.left(45)
        yield
        nah.forward(30)
        yield
        nah.left(45)
        yield
        nah.forward(40)
        yield
        nah.right(45)
        yield
        nah.forward(30)
        yield

def func2():
    for e in range(4):
        nah1.left(45)
        yield
        nah1.forward(40)
        yield
        nah1.right(45)
        yield
        nah1.forward(30)
        yield
        nah1.right(45)
        yield
        nah1.forward(40)
        yield
        nah1.left(45)
        yield
        nah1.forward(30)
        yield

然后可互换地调用这两个函数直到完成:

import itertools

for a, b in itertools.zip_longest(func1(), func2()):
    pass

*在Python2中,使用izip_longest代替zip_longest

说明

那么,它是如何运作的?

func1() anfd func2()现在返回生成器对象。这将是一种使用它们的低技术方式:

gen1 = func1()
gen2 = func2()

next(gen1)
next(gen2)
next(gen1)
next(gen2)
next(gen1)
next(gen2)
...

可以迭代生成器对象,它将产生值。在这种情况下,它只会产生None,但我们对它产生的结果不感兴趣 - 我们只是希望它暂停。

因此,这将执行整个func1

for x in func1():
    pass

为了可互换地执行func1和func2,它们被压缩。 zip_longest确保迭代在其中一个函数完成时不会停止,但会一直持续到两个函数完成为止。

答案 2 :(得分:0)

有几种方法可以解决这个问题。一种使用screen.ontimer()事件的方法(参见turtle文档)。这种方法允许您将海龟调整为实际的时钟时间。

我在下面使用的方法是将乌龟运动分解成发电机内的微小步骤,在每一点运动后产生。这与@zvone所做的类似,但程度更高(运动更平滑),对原始代码的影响更小。我也设置它来利用现有的turtle.speed()来控制两只乌龟的绝对速度和相对速度 - 如果你说turtle1.speed("快速")它与turtle2.speed("慢")相比,它会快速移动。

from turtle import Turtle, Screen

def forward(turtle, distance):
    speed = turtle.speed()
    for _ in range(0, distance, speed):
        turtle.forward(speed)
        yield 0

def func1(turtle):
    for _ in range(4):
        turtle.right(45)
        yield from forward(turtle, 40)
        turtle.left(45)
        yield from forward(turtle, 30)
        turtle.left(45)
        yield from forward(turtle, 40)
        turtle.right(45)
        yield from forward(turtle, 30)

def func2(turtle):
    for _ in range(4):
        turtle.left(45)
        yield from forward(turtle, 40)
        turtle.right(45)
        yield from forward(turtle, 30)
        turtle.right(45)
        yield from forward(turtle, 40)
        turtle.left(45)
        yield from forward(turtle, 30)

nah1 = Turtle(shape='turtle')  # first turtle
nah1.penup()
nah1.goto(-300, 200)
nah1.pendown()
nah1.speed('slowest')
generator1 = func1(nah1)

nah2 = Turtle(shape='turtle')  # second turtle
nah2.penup()
nah2.goto(-300, 180)
nah2.pendown()
nah2.speed(nah1.speed() + 1)  # a little faster than nah1
generator2 = func2(nah2)

def race_turtles():
    while (next(generator1, 1) + next(generator2, 1)) < 2:
        pass

screen = Screen()

screen.ontimer(race_turtles, 100)

screen.exitonclick()

我在screen.ontimer()事件中发起了比赛,以便整个比赛在exitonclick()召唤之后进行。这样,即使比赛正在运行,您也可以单击窗口关闭它。如果我们只是直接调用race_turtles(),那么在比赛结束之前点击屏幕就什么都不做。

来自伊索,&#34;乌龟和稍快的乌龟&#34;:

enter image description here

答案 3 :(得分:0)

  

RuntimeError:主线程不在主循环中

很多人都有这个问题,试图用龟踩踏板 - 让我们看看我们是否可以做些工作。关键的变化是不允许其他线程操纵乌龟 - 他们改为排队他们的乌龟请求并让主线程处理它们:

import queue
import threading
from turtle import Turtle, Screen

def forward(turtle, distance):
    graphics.put((turtle.forward, distance))

def right(turtle, angle):
    graphics.put((turtle.right, angle))

def left(turtle, angle):
    graphics.put((turtle.left, angle))

def func1():
    for _ in range(4):
        right(nah1, 45)
        forward(nah1, 40)
        left(nah1, 45)
        forward(nah1, 30)
        left(nah1, 45)
        forward(nah1, 40)
        right(nah1, 45)
        forward(nah1, 30)

def func2():
    for _ in range(4):
        left(nah2, 45)
        forward(nah2, 40)
        right(nah2, 45)
        forward(nah2, 30)
        right(nah2, 45)
        forward(nah2, 40)
        left(nah2, 45)
        forward(nah2, 30)

def process_queue():
    while not graphics.empty():
        graphic, argument = graphics.get()

        graphic(argument)

    if threading.active_count() > 1:
        screen.ontimer(process_queue, 100)

graphics = queue.Queue(1)  # size = number of hardware threads you have - 1

nah1 = Turtle(shape='turtle', visible=False)  # first turtle
nah1.speed('fastest')
nah1.penup()
nah1.goto(-300, 200)
nah1.pendown()
nah1.showturtle()

nah2 = Turtle(shape='turtle', visible=False)  # second turtle
nah2.speed('fastest')
nah2.penup()
nah2.goto(-300, 180)
nah2.pendown()
nah2.showturtle()

threading.Thread(target=func1).start()
threading.Thread(target=func2).start()

screen = Screen()

process_queue()

screen.exitonclick()