问题
I am currently developing a simple Tower of Hanoi animation in Pygame, that should show the correct solution of Tower of Hanoi, moving one piece per second.
However, in my hanoi solving algorithm, I'm trying to update the display and use pygame.time.wait() after each movement; and instead of updating one movement and waiting one second, the program waits the total number of movements amount of seconds and then displays the tower with all the movements done at once.
What I would like to know is if I am using the wait function wrongly or if there is any other useful function in this situation that I am missing.
Here's the code:
def hanoi(n, origin, destination, aux):
# solves the game with n pieces
if n == 1:
positions[0] = destination
# updates and waits
printBackground()
printPieces(positions)
pg.time.wait(1000)
else:
hanoi(n-1, origin, aux, destination)
positions[n-1] = destination
#updates and waits
printBackground()
printPieces(positions)
pg.time.wait(1000)
hanoi(n-1, aux, destination, origin)
and the loop:
while True:
for event in pg.event.get():
if event.type == pg.QUIT:
pg.quit()
sys.exit()
if running:
hanoi(numPieces, 0, 2, 1)
running = False
Thank you!
回答1:
You need to seperate your algorithm from the drawing aspect of your code.
A simple way to update your code would be to use a coroutine that, at every step of your recursive hanoi
function, gives the control back to the main loop, which in turn draws the screen, and gives control back to the hanoi
coroutine every second.
Here's a simplified example that just counts down:
#-*- coding-utf8 -*-
import pygame
import pygame.freetype
pygame.init()
screen = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
font = pygame.freetype.SysFont(None, 30)
def hanoi(num):
# We calculated something and want to print it
# So we give control back to the main loop
yield num
# We go to the next step of the recursive algorithm
yield from hanoi(num-1) #
steps = hanoi(1000)
ticks = None
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
exit()
# step every second only
if not ticks or pygame.time.get_ticks() - ticks >= 1000:
ticks = pygame.time.get_ticks()
screen.fill((200, 200, 200))
# the value from the next step of the coroutine
value = str(next(steps))
# render stuff onto the screen
font.render_to(screen, (100, 100), value)
pygame.display.flip()
clock.tick(60)
In your code, you should replace
# updates and waits
printBackground()
printPieces(positions)
pg.time.wait(1000)
with yield positions
to give control back to the main loop and
hanoi(n-1, aux, destination, origin)
with
yield from hanoi(n-1, aux, destination, origin)
to keep the coroutine running and call
...
screen.fill((200, 200, 200))
positions = next(steps)
printBackground()
printPieces(positions)
...
inside the if
in the main loop.
(If the algorithm finish, it will raise a StopIterationException
which you probably want to catch).
来源:https://stackoverflow.com/questions/53586802/using-pygame-time-wait-between-display-updates