from tkinter import * from tkinter.ttk import * PLAYER1 = "X" PLAYER2 = "O" SIZE = 3 # length of board side class TicTacToe: '''A graphical game of Tic Tac Toe using tkinter.''' def __init__(self, window): '''Initialize the game window components.''' window.title("Tic-Tac-Toe") style = Style() style.configure('TButton', font=('Sans', '48', 'bold'), padding=30) style.configure('TLabel', font=('Sans', '24', 'bold')) self.display_text = StringVar() display = Label(window, textvariable=self.display_text) display.grid(row=0, column=0, columnspan=SIZE) self.populate_board(window) self.turn = PLAYER1 self.display_text.set('Next player: ' + self.turn) def populate_board(self, window): '''Set up the buttons making up the game board.''' self.board = [] for row_num in range(SIZE): board_row = [] for col_num in range(SIZE): button_text = StringVar() button = Button( window, textvariable = button_text, command = self.button_action(row_num, col_num), width = 1 # make buttons square ) button.grid(row=row_num + 1, column=col_num) board_row.append(button_text) self.board.append(board_row) def button_action(self, row_num, col_num): '''Construct a callback function for the given (row, col).''' def button_callback(): '''Executes whenever a button is clicked to make a play.''' button_text = self.board[row_num][col_num] if button_text.get() == '': # making the play if self.turn == PLAYER1: button_text.set(PLAYER1) else: button_text.set(PLAYER2) # check if the active player won if self.check_win(row_num, col_num): self.display_text.set(self.turn + ' wins!') else: # switch the active player if self.turn == PLAYER1: self.turn = PLAYER2 else: self.turn = PLAYER1 self.display_text.set('Next player: ' + self.turn) return button_callback def check_win(self, row_clicked, col_clicked): '''Check whether the current player won with the last (row_clicked, col_clicked) play.''' # check if row row_clicked is a winner win_so_far = True for col in range(SIZE): # check (row_clicked, col) if self.board[row_clicked][col].get() != self.turn: # not a win in this row win_so_far = False break if win_so_far: return True # check if col col_clicked is a winner win_so_far = True for row in range(SIZE): # check (row, col_clicked) if self.board[row][col_clicked].get() != self.turn: # not a win in this col win_so_far = False break if win_so_far: return True # check diags win_so_far = True for i in range(SIZE): if self.board[i][i].get() != self.turn: # not a win in this diag win_so_far = False break if win_so_far: return True # check diags win_so_far = True for i in range(3): if self.board[i][SIZE - 1 - i].get() != self.turn: # not a win in this diag win_so_far = False break if win_so_far: return True # otherwise, not a winner return False def main(): window = Tk() TicTacToe(window) window.mainloop() main()