Adventures in Machine Learning

Python Tic-Tac-Toe: Building a Game Board with Tkinter

Tic-tac-toe is a classic game that has entertained people for generations. While it may seem simple on the surface, it can be a challenging and fun game to play with others.

In this article, we will walk you through the process of setting up a tic-tac-toe game board with Tkinter and setting up tic-tac-toe game logic in Python.

Setting Up Tic-Tac-Toe Game Board with Tkinter

Tkinter is a Python library used to create graphical user interfaces. It provides a wide variety of tools to create windows, buttons, text fields, and other graphical elements.

The first step towards setting up a tic-tac-toe game board is creating the game board with Tkinter. We begin by importing the tkinter library in Python:

“` Python

import tkinter as tk

“`

Next, we create a window to hold the game board with the following code:

“` Python

window = tk.Tk()

window.title(“Tic Tac Toe”)

“`

The above code creates a window and sets its title to “Tic Tac Toe”. We can customize the window’s dimensions using the `geometry()` method.

“` Python

window.geometry(“300×300”)

“`

This code sets the window’s width and height to 300 pixels. We can now create a 3×3 playing grid by using a combination of `Frame` and `Label` objects.

“` Python

board = tk.Frame(window)

board.grid()

for i in range(3):

for j in range(3):

cell = tk.Label(board, width=10, height=5, relief=’sunken’)

cell.grid(row=i, column=j)

“`

The `Frame` object creates a group of widgets, which can make it easier to manage and manipulate the game board. The nested `for` loop creates 9 `Label` objects, representing the 9 cells of the game board.

The `width` and `height` parameters give the cells their dimensions. The `relief` parameter sets the border style for each cell.

Placing the game board on the screen

We have created a game board, but it is not yet visible on the screen. We need to call the `mainloop()` method to activate the window, which we can do by adding this code at the end of our program:

“` Python

window.mainloop()

“`

This code runs the Tkinter event loop, which enables us to interact with the game board.

Once we run the program, the game board should appear on the screen.

Setting Up Tic-Tac-Toe Game Logic in Python

The next step is to set up the game logic in Python. To do this, we need to define classes for players and their moves, create a class to represent game logic, set up the abstract game board, and figure out the winning combinations.

Defining classes for players and their moves

We can create a class for each player, which will store their name and the cells they have marked on the game board. “` Python

class Player:

def __init__(self, name, symbol):

self.name = name

self.symbol = symbol

self.moves = []

def mark_cell(self, cell):

self.moves.append(cell)

“`

The `Player` class has an `__init__` method that creates the player’s name, symbol, and an empty `moves` list to store the cells they have marked.

The `mark_cell` method adds a cell to the player’s moves list when they mark it.

Creating a class to represent game logic

We can create a `Game` class to handle the game’s logic. This class will initialize the game board, keep track of player turns, and check for winning combinations.

“` Python

class Game:

def __init__(self, player1, player2):

self.board = [[” for i in range(3)] for j in range(3)]

self.player1 = player1

self.player2 = player2

self.current_player = player1

def mark_cell(self, row, col):

if self.board[row][col] == ”:

self.board[row][col] = self.current_player.symbol

self.current_player.mark_cell((row, col))

self.switch_player()

def switch_player(self):

if self.current_player == self.player1:

self.current_player = self.player2

else:

self.current_player = self.player1

def get_winner(self):

for i in range(3):

if self.board[i][0] == self.board[i][1] == self.board[i][2] != ”:

return self.current_player

elif self.board[0][i] == self.board[1][i] == self.board[2][i] != ”:

return self.current_player

if self.board[0][0] == self.board[1][1] == self.board[2][2] != ”:

return self.current_player

elif self.board[0][2] == self.board[1][1] == self.board[2][0] != ”:

return self.current_player

elif all(self.board[i][j] != ” for i in range(3) for j in range(3)):

return ‘Draw’

else:

return None

“`

The `Game` class initializes the game board as a 3×3 matrix of empty cells and sets the first player to be `player1`. The `mark_cell` method checks if the selected cell is empty, marks the cell with the current player’s symbol, and updates their moves list.

It then switches the current player to the other player. The `get_winner` method checks each row, column, and diagonal to see if there are three matching symbols in a row.

If this condition is met, it returns the current player. If all cells on the board have been marked but there is no winner, it returns “Draw”.

If there is no winner yet, it returns `None`.

Setting up the abstract game board

Now that we have set up the game logic, we need to track the moves of each player on the abstract game board. We can do this by creating a 3×3 matrix of tuples representing each cell on the game board.

“` Python

board = [[(i, j) for j in range(3)] for i in range(3)]

“`

We can use this matrix to map each cell to its corresponding button on the game board. “` Python

board_buttons = [[None for j in range(3)] for i in range(3)]

for i in range(3):

for j in range(3):

button = tk.Button(board, text=”, font=’Arial 30′, width=4, height=2,

command=lambda row=i, col=j: self.mark_cell(row, col))

button.grid(row=i, column=j)

board_buttons[i][j] = button

“`

This code creates a `Button` object for each cell and maps it to the corresponding cell in the `board_buttons` matrix.

The `command` parameter specifies what function to call when the button is clicked, which in this case is the `mark_cell` method of the `Game` class.

Figuring out the winning combinations

The final step is to figure out the winning combinations. We can use the `get_winner` method of the `Game` class to check if there is a winner after each move.

“` Python

winner = game.get_winner()

if winner is not None:

if winner == ‘Draw’:

message = ‘It is a draw!’

else:

message = winner.name + ‘ has won!’

tk.messagebox.showinfo(‘Game Over’, message)

“`

This code checks if there is a winner. If there is a winner, it displays a message box with the winner’s name or “Draw”.

Conclusion

In this article, we have walked you through the process of setting up a tic-tac-toe game board with Tkinter and setting up tic-tac-toe game logic in Python. By following these steps, you can create your own tic-tac-toe game that can be played on your computer.

We hope this article has been informative and that you will enjoy creating and playing your own tic-tac-toe game. In the last section, we covered the initial steps of setting up a tic-tac-toe game board with Tkinter and defining game logic in Python.

In this section, we will be exploring further enhancements to the codebase by defining the TicTacToeBoard class along with added functionality. We will also discuss how to handle player interaction, process player moves, determine the winner, and add logic to handle tie games.

Defining the TicTacToeBoard class

The TicTacToeBoard class is responsible for displaying the game board to the user and updating it with the current state of the game. We will start by defining this class, which will hold an instance of the game board state, an instance of the Game class discussed earlier, and the various visual elements of the game board that will be displayed to the user.

“` Python

class TicTacToeBoard(Frame):

def __init__(self, master=None):

super().__init__(master)

self.game_state = [[None for _ in range(3)] for _ in range(3)]

self.game = Game()

self.current_player = 1

self.init_ui()

“`

The `__init__` method initializes the state of the game with a 3×3 matrix that holds None values, an instance of the Game class, and the current player, which is set to player 1. We call the `init_ui` method to display the game board on the screen.

Adding functionality to the TicTacToeBoard class

Now that we’ve defined the TicTacToeBoard class, we’re ready to add functionality to it. This includes handling player interaction, processing player moves, determining the winner of the game, and adding logic to handle tie games.

Creating a method to process player moves

To process player moves, we need to create a method that is triggered when a player clicks a square on the game board. When the player clicks a square, we need to update the state of the game board with the player’s mark and switch turns to the next player.

“` Python

def process_move(self, row, col):

if self.game_state[row][col]:

return

self.game_state[row][col] = self.current_player

self.game.mark_board(row, col, self.current_player)

self.current_player = 1 if self.current_player == 2 else 2

“`

The code above checks if a square is already marked by a player before marking it with the current player’s mark. It then calls the `mark_board` method of the `Game` class to update the state of the game and switch turns to the next player.

Determining the winner of the game

To determine the winner of the game, we need to add a method that checks the state of the game board after each move and returns the winner. If there is no winner, it returns None.

“` Python

def check_winner(self):

winner = self.game.check_winner()

if winner:

tk.messagebox.showinfo(‘Game Over’, f'{winner.name} Wins!!’)

return winner.symbol

return None

“`

This code delegates the task of checking the winner to the `check_winner` method of the `Game` class. If there is a winner, it displays a message box with the winner’s name and returns their symbol.

Otherwise, it returns None.

Adding logic to handle tie games

Finally, we need to add logic to handle tie games. In the case where all squares are marked and no winner is found, the game should display a message box with information that the game is a tie.

“` Python

def check_tie(self):

if all(all(x for x in row) for row in self.game_state):

tk.messagebox.showinfo(‘Game Over’, ‘Tie Game’)

return True

return False

“`

This code checks if all squares are marked and no winner is found. If so, it displays a message box with the information that the game is tied.

Putting it all together

Here’s how the updated TicTacToeBoard class looks when all the added functionality is put together:

“` Python

class TicTacToeBoard(Frame):

def __init__(self, master=None):

super().__init__(master)

self.game_state = [[None for _ in range(3)] for _ in range(3)]

self.game = Game()

self.current_player = 1

self.init_ui()

def init_ui(self):

for i in range(3):

for j in range(3):

btn = Button(self, height=3, width=6)

btn[‘command’] = lambda row=i, col=j: self.process_move(row, col)

btn.grid(row=i, column=j)

self.game.add_player_mark(i, j, btn)

def process_move(self, row, col):

if self.game_state[row][col]:

return

self.game_state[row][col] = self.current_player

self.game.mark_board(row, col, self.current_player)

self.current_player = 1 if self.current_player == 2 else 2

self.check_winner()

self.check_tie()

def check_winner(self):

winner = self.game.check_winner()

if winner:

tk.messagebox.showinfo(‘Game Over’, f'{winner.name} Wins!!’)

return winner.symbol

return None

def check_tie(self):

if all(all(x for x in row) for row in self.game_state):

tk.messagebox.showinfo(‘Game Over’, ‘Tie Game’)

return True

return False

“`

The `init_ui` method is responsible for creating and organizing the button elements in a 3×3 format. We assign a callback function to each button command that calls the `process_move` method to mark the selected cell with the current player’s marker.

The `check_winner` and `check_tie` methods handle the logic for determining a winner or a tie in the game.

Conclusion

In this section, we have added more functionality to the TicTacToeBoard class, including processing player moves, handling the logic for determining a winner or a tie in the game, and extended the game functionality. Together, these functionalities make for a polished and enjoyable Tic Tac Toe game that you can play on your computer.

We hope this article has been insightful and that you will have fun building your own version of this classic game. In the last section, we discussed how to enhance the TicTacToeBoard class to handle player interaction and determine the winner of the game.

In this section, we will explore how to create the game interface with Tkinter, add buttons to the game interface, link the game board to the game interface, and run the Tic-Tac-Toe game.

Creating the game interface with Tkinter

We start by creating a window to hold the game interface with the following code:

“` Python

class GameInterface(Frame):

def __init__(self):

super().__init__()

self.master.title(‘Tic Tac Toe’)

self.master.resizable(width=True, height=True)

self.pack(fill=BOTH, expand=True)

self.board = TicTacToeBoard(self)

self.board.pack(fill=BOTH, expand=True)

“`

This code creates a window and sets its title to “Tic Tac Toe”. We use the `pack()` method to place the TicTacToeBoard object, which is responsible for displaying the game board, within the window.

Adding buttons to the game interface

Next, we add buttons to the game interface to allow the user to reset the game board and exit the game. We can do this by defining two new methods in the `GameInterface` class that create and position the buttons.

“` Python

class GameInterface(Frame):

def __init__(self):

# … self.add_buttons()

def add_buttons(self):

reset_button = Button(self, text=’Reset’, command=self.reset_board)

reset_button.pack(side=LEFT, padx=5, pady=5)

exit_button = Button(self, text=’Exit’, command=self.quit)

exit_button.pack(side=RIGHT, padx=5, pady=5)

def reset_board(self):

self.board.reset()

“`

The `add_buttons()` method creates a “Reset” button and an “Exit” button and packs them into the window using the `pack()` method.

The `reset_board()` method is bound to the “Reset”

Popular Posts