Begin removing some duplicated parts
In the following methods
From the evt parameter, you can obtain the character of the key pressed using its char attribute.
A single function can be created to replace all of the number keys events
The remaining key binds
There is a repeated pattern here
In the following methods
def playZero(self, evt): if self.board[0] == 0 and self.gameover == False: self.board[0] = 1 self.advanceTurn() def playOne(self, evt): if self.board[1] == 0 and self.gameover == False: self.board[1] = 1 self.advanceTurn() def playTwo(self, evt): if self.board[2] == 0 and self.gameover == False: self.board[2] = 1 self.advanceTurn() def playThree(self, evt): if self.board[3] == 0 and self.gameover == False: self.board[3] = 1 self.advanceTurn() def playFour(self, evt): if self.board[4] == 0 and self.gameover == False: self.board[4] = 1 self.advanceTurn() def playFive(self, evt): if self.board[5] == 0 and self.gameover == False: self.board[5] = 1 self.advanceTurn() def playSix(self, evt): if self.board[6] == 0 and self.gameover == False: self.board[6] = 1 self.advanceTurn() def playSeven(self, evt): if self.board[7] == 0 and self.gameover == False: self.board[7] = 1 self.advanceTurn() def playEight(self, evt): if self.board[8] == 0 and self.gameover == False: self.board[8] = 1 self.advanceTurn()the only thing that changes is the board index number.
From the evt parameter, you can obtain the character of the key pressed using its char attribute.
A single function can be created to replace all of the number keys events
def play_number(self, evt): index = int(evt.char) if self.board[index] == 0 and self.gameover == False: self.board[index] = 1 self.advanceTurn()The event binding now becomes
self.gamecanvas.bind_all('<KeyPress-0>', self.play_number) self.gamecanvas.bind_all('<KeyPress-1>', self.play_number) self.gamecanvas.bind_all('<KeyPress-2>', self.play_number) self.gamecanvas.bind_all('<KeyPress-3>', self.play_number) self.gamecanvas.bind_all('<KeyPress-4>', self.play_number) self.gamecanvas.bind_all('<KeyPress-5>', self.play_number) self.gamecanvas.bind_all('<KeyPress-6>', self.play_number) self.gamecanvas.bind_all('<KeyPress-7>', self.play_number) self.gamecanvas.bind_all('<KeyPress-8>', self.play_number)This also has repeated code that only the number changes and can be replaced with
for number in range(9): self.gamecanvas.bind_all(f'<KeyPress-{number}>', self.play_number)
The remaining key binds
self.gamecanvas.bind_all('<KeyPress-y>', self.restart) self.gamecanvas.bind_all('<KeyPress-Y>', self.restart) self.gamecanvas.bind_all('<KeyPress-n>', self.endgame) self.gamecanvas.bind_all('<KeyPress-N>', self.endgame) self.gamecanvas.bind_all('<KeyPress-Return>', self.closegame)only the key character and the bind method changes, this could be done by using a tuple
key_binds = (('y', self.restart), ('Y', self.restart), ('n', self.endgame), ('N', self.endgame), ('Return', self.closegame)) for key, bind in key_binds: self.gamecanvas.bind_all(f'<KeyPress-{key}>', bind)
There is a repeated pattern here
canvas.create_text(100, 100, text=board[0], font=('Times', 80)) canvas.create_text(200, 100, text=board[1], font=('Times', 80)) canvas.create_text(300, 100, text=board[2], font=('Times', 80)) canvas.create_text(100, 200, text=board[3], font=('Times', 80)) canvas.create_text(200, 200, text=board[4], font=('Times', 80)) canvas.create_text(300, 200, text=board[5], font=('Times', 80)) canvas.create_text(100, 300, text=board[6], font=('Times', 80)) canvas.create_text(200, 300, text=board[7], font=('Times', 80)) canvas.create_text(300, 300, text=board[8], font=('Times', 80))that could be looped
index = 0 for y in (range(100, 400, 100)): for x in (range(100, 400, 100)): canvas.create_text(x, y, text=board[index], font=('Times', 80)) index += 1