I'm trying to write a GUI to display the Knights Tour backtracking algorithm. I have the algorithm working but when running the GUI, it becomes unresponsive after a few seconds.
import pygame
import time
# Init Gui
pygame.init()
# Window Size
WIN_DIMENSION = 800
win = pygame.display.set_mode((WIN_DIMENSION, WIN_DIMENSION))
pygame.display.set_caption("Knights Tour")
# Board Size
N = 8
TARGETMOVES = N**2
# Colors
white = (255, 255, 255)
black = (0, 0, 0)
red = (180, 0, 0)
def DisplayGui(board, final=False):
win.fill(black)
for i in range(N):
ydraw = i * (WIN_DIMENSION/N)
for n in range(N):
xdraw = n * (WIN_DIMENSION / N)
pygame.draw.rect(win, red, (xdraw, ydraw, WIN_DIMENSION/N, WIN_DIMENSION/N), 3)
displayText(board[i][n], xdraw, ydraw)
while final:
for event in pygame.event.get():
if event.type == pygame.QUIT:
final = False
print("CLOSING")
pygame.display.update()
#time.sleep(1)
def text_objects(text, font):
textSurface = font.render(str(text), True, white)
return textSurface, textSurface.get_rect()
def displayText(text, xdraw, ydraw):
font = pygame.font.Font('freesansbold.ttf', 7 * N)
TextSurf, TextRect = text_objects(text, font)
TextRect.center = ((xdraw + (WIN_DIMENSION / N) / 2), (ydraw + (WIN_DIMENSION / N) / 2))
win.blit(TextSurf, TextRect)
def checkValid(board, movx, movy):
'''
params:
movx => next x move
movy => next y move
checks if move is valid
'''
if (movx >= 0 and movy >= 0 and movx < N and movy < N and board[movx][movy] == " "):
return True
return False
def printBoard(board):
'''
Prints Board
'''
for i in range(len(board)):
print(board[i])
def KnightsTour():
currx = 0
curry = 0
# Init board
board = [[" " for i in range(N)] for i in range(N)]
xmoves = [-2, -2, -1, -1, 1, 1, 2, 2]
ymoves = [1, -1, 2, -2, 2, -2, 1, -1]
totalmoves = 1
board[0][0] = 0
DisplayGui(board)
if generateMove(board, currx, curry, totalmoves, xmoves, ymoves):
printBoard(board)
DisplayGui(board, True)
else: print("Invalid")
def generateMove(board, currx, curry, totalmoves, xmoves, ymoves):
if totalmoves == TARGETMOVES:
return True
print("X: {} <> Y: {}".format(currx, curry)) # draw board here
DisplayGui(board)
for i in range(8):
nextx = currx + xmoves[i]
nexty = curry + ymoves[i]
if checkValid(board, nextx, nexty):
board[nextx][nexty] = totalmoves
if generateMove(board, nextx, nexty, totalmoves+1, xmoves, ymoves):
return True
# backtracking
board[nextx][nexty] = " "
return False
if __name__ == "__main__":
KnightsTour()
I tried to slow it down using sys.sleep() but that didn't help it. I have no idea whats causing the GUI to freeze. The algo still runs in the background.
If you want to overcome this problem without changing your code significantly you can call pygame.event.pump() in your DisplayGui()
function. This will make your operating system / window manager believe that your program hasn't frozen.
def DisplayGui(board, final=False):
win.fill(black)
if not final:
pygame.event.pump()
for i in range(N):
...
It would be more helpful to actually handle QUIT events so you could end the program prematurely without ending the python process.
If you're considering reorganising your code, perhaps this openbook would be useful. This section describes a standard game loop which should look something like:
event handling → update state → draw new state → update display