如何在Python中同时运行两个while循环?

时间:2022-05-30 00:14:35

I am new to Python and using Zelle's graphics to create a game. I need the two while loops below to run at the same time, however I am running into difficulty. I tried nesting the while loops but then the horses and civilians would only move if the mouse was clicked, which I don't want. What I want is for the horses and civilians to always be moving, and the princess to move only when the mouse is clicked, and stop the game with a "game over" when she has saved 10 civilians.

我是Python的新手,并使用Zelle的图形来创建游戏。我需要下面的两个while循环同时运行,但是我遇到了困难。我尝试嵌套while循环,但是马和平民只有在点击鼠标时才会移动,这是我不想要的。我想要的是马匹和平民总是在移动,公主只有在点击鼠标时才能移动,并且当她拯救了10名平民时,通过“游戏结束”停止游戏。

    # animation loop.
while True==True:

    for horse in horseList:
        if horse.leg.getX() > -187:
            horse.move( -1, 20 )
        else:
            horse.move( 5, 28 )

    for civilian in civiliansList:

        if civilian.getX() < 800:
            civilian.move( 20, 0 )
        else:
            civilian.move( -100, 0 )

while civiliansSaved != 10:

    mouse = win.getMouse()

    princess.move( mouse, civilianCounter)

    civilianCounter = princess.move( mouse, civilianCounter)
    # move is a method that will return an updated civilianCounter ( it is initially 0 and defined outside of the while loop ), depending on whether princess runs into civilians

else:
    print( "Game over" )
    win.getMouse()
    win.close()

3 个解决方案

#1


Just use checkMouse() instead of getMouse() inside your animation loop.

只需在动画循环中使用checkMouse()而不是getMouse()。

Simple as that, I think.

我认为这很简单。

while civiliansSaved < 11:

    for horse in horseList:
        if horse.leg.getX() > -187      
            horse.move( -1, 20 )
        else:
            horse.move( 5, 28 )

    for civilian in civiliansList:
        if civilian.getX() < 800:
            civilian.move( 20, 0 )
        else:
            civilian.move( -100, 0 )

    mouse = win.checkMouse()

    if mouse:
        princess.move( mouse, civilianCounter)
        civilianCounter = princess.move( mouse, civilianCounter)

print( "Game over" )
win.getMouse()
win.close()

Doco:

checkMouse() Similar to getMouse, but does not pause for a user click. Returns the latest point where the mouse was clicked or None if the window as not been clicked since the previous call to checkMouse or getMouse. This is particularly useful for controlling simple animation loops.

checkMouse()与getMouse类似,但不会暂停用户单击。返回单击鼠标的最新点,如果自上次调用checkMouse或getMouse后未单击窗口,则返回None。这对于控制简单动画循环特别有用。

#2


Here is an example that should do what you want without the need for parallel processing (which is tricky in python):

这是一个应该做你想要的而不需要并行处理的例子(这在python中很棘手):

while True:  # you don't need to write True==True
    for horse in horseList:
        if horse.leg.getX() > -187:
            horse.move( -1, 20 )
        else:
            horse.move( 5, 28 )

    for civilian in civiliansList:  
        if civilian.getX() < 800:
            civilian.move( 20, 0 )
        else:
            civilian.move( -100, 0 )

    mouse = win.getMouse()
    princess.move( mouse, civilianCounter)
    civilianCounter = princess.move( mouse, civilianCounter)

    if civiliansSaved >= 10: # check to see if 10 or more have been saved
        break
        print( "Game over" )
        win.getMouse()
        win.close()

What you want to do is to keep the game running until the civilianSaved counter is at least 10. But you can't do that in a separate loop from your main game loop, so it makes more sense to not stop the game until the count is at least 10. This if statement can be included in your main game loop.

你想要做的是保持游戏运行,直到civilSaved计数器至少为10.但是你不能在主游戏循环的单独循环中这样做,所以在计数之前不要停止游戏更有意义这个if语句可以包含在你的主游戏循环中。

#3


Zelle's graphics is not an event driven graphics tool, which I think is what you are looking for. Maybe consider switching to tkinter which is part of the Python standard library. You can use a callback function to handle mouse events so that your app is free to do other things while it is waiting to process a mouse event.

Zelle的图形不是一个事件驱动的图形工具,我认为这是你正在寻找的。也许考虑切换到tkinter,这是Python标准库的一部分。您可以使用回调函数来处理鼠标事件,以便您的应用程序在等待处理鼠标事件时可以*地执行其他操作。

tkinter has an after() feature which allows you to call a function after a specified period of time. You can create separate functions for civilian movement and horse movement and call these functions after a specified period of time (say 50 ms). This effectively simulates running the functions in parallel and allows horses and civilians to move at the same time, at least from the user's perspective. You would need another call to after() within the movement functions so that they are continuously called.

tkinter具有after()功能,允许您在指定的时间段后调用函数。您可以为民用运动和马运动创建单独的功能,并在指定的时间段(例如50毫秒)后调用这些功能。这有效地模拟了并行运行功能,并允许马匹和平民同时移动,至少从用户的角度来看。你需要在移动函数中再调用after(),以便连续调用它们。

self.root.after(50, self.process_horse_movement)
self.root.after(50, self.process_civilian_movement)

Then at the end of each movement function:

然后在每个运动功能结束时:

def process_horse_movement():
    ...
    self.root.after(50, self.process_horse_movement)

def process_civilian_movement():
    ...
    self.root.after(50, self.process_civilian_movement)

Also, a minor point. Use while True: instead of while True == True:.

还有一个小问题。使用True:而不是True == True:

#1


Just use checkMouse() instead of getMouse() inside your animation loop.

只需在动画循环中使用checkMouse()而不是getMouse()。

Simple as that, I think.

我认为这很简单。

while civiliansSaved < 11:

    for horse in horseList:
        if horse.leg.getX() > -187      
            horse.move( -1, 20 )
        else:
            horse.move( 5, 28 )

    for civilian in civiliansList:
        if civilian.getX() < 800:
            civilian.move( 20, 0 )
        else:
            civilian.move( -100, 0 )

    mouse = win.checkMouse()

    if mouse:
        princess.move( mouse, civilianCounter)
        civilianCounter = princess.move( mouse, civilianCounter)

print( "Game over" )
win.getMouse()
win.close()

Doco:

checkMouse() Similar to getMouse, but does not pause for a user click. Returns the latest point where the mouse was clicked or None if the window as not been clicked since the previous call to checkMouse or getMouse. This is particularly useful for controlling simple animation loops.

checkMouse()与getMouse类似,但不会暂停用户单击。返回单击鼠标的最新点,如果自上次调用checkMouse或getMouse后未单击窗口,则返回None。这对于控制简单动画循环特别有用。

#2


Here is an example that should do what you want without the need for parallel processing (which is tricky in python):

这是一个应该做你想要的而不需要并行处理的例子(这在python中很棘手):

while True:  # you don't need to write True==True
    for horse in horseList:
        if horse.leg.getX() > -187:
            horse.move( -1, 20 )
        else:
            horse.move( 5, 28 )

    for civilian in civiliansList:  
        if civilian.getX() < 800:
            civilian.move( 20, 0 )
        else:
            civilian.move( -100, 0 )

    mouse = win.getMouse()
    princess.move( mouse, civilianCounter)
    civilianCounter = princess.move( mouse, civilianCounter)

    if civiliansSaved >= 10: # check to see if 10 or more have been saved
        break
        print( "Game over" )
        win.getMouse()
        win.close()

What you want to do is to keep the game running until the civilianSaved counter is at least 10. But you can't do that in a separate loop from your main game loop, so it makes more sense to not stop the game until the count is at least 10. This if statement can be included in your main game loop.

你想要做的是保持游戏运行,直到civilSaved计数器至少为10.但是你不能在主游戏循环的单独循环中这样做,所以在计数之前不要停止游戏更有意义这个if语句可以包含在你的主游戏循环中。

#3


Zelle's graphics is not an event driven graphics tool, which I think is what you are looking for. Maybe consider switching to tkinter which is part of the Python standard library. You can use a callback function to handle mouse events so that your app is free to do other things while it is waiting to process a mouse event.

Zelle的图形不是一个事件驱动的图形工具,我认为这是你正在寻找的。也许考虑切换到tkinter,这是Python标准库的一部分。您可以使用回调函数来处理鼠标事件,以便您的应用程序在等待处理鼠标事件时可以*地执行其他操作。

tkinter has an after() feature which allows you to call a function after a specified period of time. You can create separate functions for civilian movement and horse movement and call these functions after a specified period of time (say 50 ms). This effectively simulates running the functions in parallel and allows horses and civilians to move at the same time, at least from the user's perspective. You would need another call to after() within the movement functions so that they are continuously called.

tkinter具有after()功能,允许您在指定的时间段后调用函数。您可以为民用运动和马运动创建单独的功能,并在指定的时间段(例如50毫秒)后调用这些功能。这有效地模拟了并行运行功能,并允许马匹和平民同时移动,至少从用户的角度来看。你需要在移动函数中再调用after(),以便连续调用它们。

self.root.after(50, self.process_horse_movement)
self.root.after(50, self.process_civilian_movement)

Then at the end of each movement function:

然后在每个运动功能结束时:

def process_horse_movement():
    ...
    self.root.after(50, self.process_horse_movement)

def process_civilian_movement():
    ...
    self.root.after(50, self.process_civilian_movement)

Also, a minor point. Use while True: instead of while True == True:.

还有一个小问题。使用True:而不是True == True: