【问题标题】:How to run while loop in the background如何在后台运行while循环
【发布时间】:2019-04-02 13:48:53
【问题描述】:

我正在尝试编写一个回合制游戏,其中有些事情需要不止一个回合才能发生。我发现在函数中放置一个while循环可以使需要一些轮流的动作起作用。这是我的测试:

#This function is supposed to 'work' after 3 turns
def action(current_turn):
    while global_turn - current_turn != 3:
        pass
    test = "works"

test = "doesn't work"
game =True
global_turn = 0
while game:
    global_turn += 1
    print(f'\nThis is turn #{global_turn}\n')
    user_input = input('Do [1]yes [2]no')
    if user_input == '2':
        pass
    elif user_input == '1':
        action(global_turn)

我认为这会一直打印“This is turn #{global_turn}”,即使我调用了该函数但它只是坐在那里。有什么方法可以让 while 循环继续进行,同时继续进行外部循环?

【问题讨论】:

    标签: python-3.x while-loop


    【解决方案1】:

    试试这个代码:

    #This function is supposed to 'work' after 3 turns
    def action(current_turn, action_turn):
        if global_turn != action_turn:
            return
        print('action!')
    
    game = True
    global_turn = 0
    action_turn = None
    while game:
        global_turn += 1
        print(f'\nThis is turn #{global_turn}\n')
        user_input = input('Do [1]yes [2]no')
        if user_input == '2':
            pass
        elif user_input == '1':
            action_turn = global_turn + 3
        action(global_turn, action_turn)
    

    注意:这实际上并没有在后台运行 while 循环。在您的示例中,这似乎没有必要。但是,如果您的游戏变得更复杂,您可能需要研究一下

    在后台运行。


    编辑

    asyncio 版本:

    import asyncio
    
    
    class Game:
        def __init__(self):
            self.game_running = True
            self.global_turn = 0
            self.turn_started = asyncio.Event()
            self.turn_ended = asyncio.Event()
    
        async def action(self, wait_turns):
            while wait_turns > 0:
                await self.turn_ended.wait()
                await self.turn_started.wait()
                wait_turns -= 1
            print('action!')
    
    
        async def main(self):
            while self.game_running:
                self.global_turn += 1
                print(f'\nThis is turn #{self.global_turn}\n')
                self.turn_ended.clear()
                self.turn_started.set()
                await asyncio.sleep(0)  # yield control to other tasks
                user_input = input('Do [1]yes [2]no')
                if user_input == '2':
                    pass
                elif user_input == '1':
                    asyncio.ensure_future(self.action(3))
                self.turn_started.clear()
                self.turn_ended.set()
                await asyncio.sleep(0)  # yield control to other tasks
    
    
    if __name__ == '__main__':
        game = Game();
        loop = asyncio.get_event_loop()
        loop.run_until_complete(game.main())
    

    说明:

    • 当用户输入1 时,action 协程使用asyncio.ensure_future 在“后台”调度
    • 每转一圈会设置两个asyncio.Event 信号。一个用于转弯开始,一个用于转弯结束。
    • action 协程在打印“action”之前等待定义的轮数开始和结束
    • action 协程可以在后台运行多次,每次倒计时直到激活。
    • await asyncio.sleep(0)action 协程继续运行所必需的。
    • 如果您需要在main 函数等待用户输入时激活操作,您可以使用aioconsole.ainput

      from aioconsole import ainput
      
      async def main(self):
          [...]
          user_input = await ainput("Do [1]yes [2]no")
          [...]
      

    【讨论】:

    • 事情是在我的游戏中有3个玩家,你可以在一个回合中进行多个动作。
    • @bajotupie 我为我的答案添加了另一个解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-01
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多