#python-3.x #while-loop
#python-3.x #цикл while
Вопрос:
Я пытаюсь запрограммировать пошаговую игру, в которой для выполнения некоторых действий требуется более одного хода. Я выяснил, что включение цикла 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 продолжаться, одновременно продолжая работу с внешним циклом?
Ответ №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
Сопрограмма может выполняться несколько раз в фоновом режиме, каждый раз отсчитывая количество оборотов, пока не станет активным.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") [...]
Комментарии:
1. Дело в том, что в моей игре 3 игрока, и вы можете совершать несколько действий за ход.
2. @bajotupie Я добавил другое решение к своему ответу