Introduction
This project will guide you through the steps to create a Tic-Tac-Toe game using Pygame. Tic-Tac-Toe is a two-player game where the goal is to get three of your symbols in a row, either horizontally, vertically, or diagonally. In this project, you will learn how to set up the game window, draw the game board, handle player and AI moves, and determine the winner. By the end of this project, you will have a fully functional Tic-Tac-Toe game that you can play against an AI opponent.
👀 Preview

🎯 Tasks
In this project, you will learn:
- How to create the project files and import the necessary libraries
- How to initialize PyGame and set up the game window
- How to define the symbols, colors, and game state
- How to define the button properties and create helper functions
- How to create the main game loop and implement the helper functions
- How to fill in the remaining code inside the main game loop
🏆 Achievements
After completing this project, you will be able to:
- Use Pygame to create a graphical game
- Draw graphics on a window using Pygame
- Handle user input and update the game state
- Implement game logic such as checking for a win condition
- Create a game loop to keep the game running
Create the project files
To begin, create a new file named tic_tac_toe.py. Open the file in your preferred text editor.
cd ~/project
touch tic_tac_toe.py
Import the necessary libraries
In tic_tac_toe.py, import the necessary libraries: pygame and random. These libraries will be used for handling the game graphics and generating random AI moves, respectively.
import pygame
import random
Install the pygame library using the following command:
sudo pip install pygame
Initialize PyGame and set up the game window
In tic_tac_toe.py, initialize PyGame using pygame.init(). Then, set up the game window by defining the window width and height, background color, line color, and cell size. Also, create a PyGame window with the specified width and height and set the window caption.
pygame.init()
WIDTH = 600
HEIGHT = 600
BACKGROUND_COLOR = (40, 40, 40)
LINE_COLOR = (70, 70, 70)
CELL_SIZE = WIDTH // 3
win = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Tic-Tac-Toe")
Define the symbols and colors
In tic_tac_toe.py, define the symbols and colors for the player and AI. These symbols and colors will be used to draw the player and AI moves on the game board.
PLAYER_SYMBOL = "X"
AI_SYMBOL = "O"
PLAYER_COLOR = (0, 255, 0)
AI_COLOR = (255, 0, 0)
EMPTY_COLOR = (0, 0, 0)
Define the game state
In tic_tac_toe.py, define the initial game state. This includes the game board, the current turn (either "player" or "ai"), a flag indicating if the game is over, and the winner of the game.
board = [["" for _ in range(3)] for _ in range(3)]
turn = "player"
game_over = False
winner = None
Define button properties
In tic_tac_toe.py, define the properties for the reset button, including the button width, height, color, text color, and font size. Also, create a reset_button_rect object using the pygame.Rect class to represent the button's position and size.
BUTTON_WIDTH = 200
BUTTON_HEIGHT = 50
BUTTON_COLOR = (50, 50, 50)
BUTTON_TEXT_COLOR = (255, 255, 255)
BUTTON_FONT = pygame.font.Font(None, 30)
reset_button_rect = pygame.Rect(
(WIDTH - BUTTON_WIDTH) // 2,
(HEIGHT - BUTTON_HEIGHT) // 2,
BUTTON_WIDTH,
BUTTON_HEIGHT,
)
Create helper functions
In tic_tac_toe.py, define several helper functions that will be used throughout the game.
draw_board(): This function will draw the game board on the window.draw_symbols(): This function will draw the player and AI symbols on the game board.is_board_full(): This function will check if the game board is full.is_winner(): This function will check if a player has won the game.make_move(): This function will make a move on the game board.player_move(): This function will handle the player's move.ai_move(): This function will handle the AI's move.check_game_over(): This function will check if the game is over.draw_winner(): This function will draw the winner message on the window.draw_reset_button(): This function will draw the reset button on the window.reset_game(): This function will reset the game state.
## Helper functions
def draw_board():
## Draw the game board
pass
def draw_symbols():
## Draw the player and AI symbols on the game board
pass
def is_board_full():
## Check if the game board is full
pass
def is_winner(symbol):
## Check if a player has won the game
pass
def make_move(x, y, symbol):
## Make a move on the game board
pass
def player_move():
## Handle the player's move
pass
def ai_move():
## Handle the AI's move
pass
def check_game_over():
## Check if the game is over
pass
def draw_winner():
## Draw the winner message on the window
pass
def draw_reset_button():
## Draw the reset button on the window
pass
def reset_game():
## Reset the game state
pass
Create the main game loop
In tic_tac_toe.py, create the main game loop using a while loop. This loop will run until the user closes the game window. Inside the game loop, handle the user's input events and update the game state accordingly.
## Main game loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
if reset_button_rect.collidepoint(event.pos):
reset_game()
elif not game_over and turn == "player":
player_move()
if not game_over and turn == "ai":
ai_move()
check_game_over()
draw_board()
draw_symbols()
if game_over:
draw_winner()
draw_reset_button()
pygame.display.flip()
## Quit the game
pygame.quit()
Implement the helper functions
Now, let's implement the helper functions we defined earlier. Start by completing the draw_board() function. This function will draw the game board on the window by drawing vertical and horizontal lines using the pygame.draw.line() function.
## Helper functions
def draw_board():
win.fill(BACKGROUND_COLOR)
## Draw vertical lines
for x in range(1, 3):
pygame.draw.line(
win, LINE_COLOR, (CELL_SIZE * x, 0), (CELL_SIZE * x, HEIGHT), 2
)
## Draw horizontal lines
for y in range(1, 3):
pygame.draw.line(win, LINE_COLOR, (0, CELL_SIZE * y), (WIDTH, CELL_SIZE * y), 2)
Implement the remaining helper functions
Next, implement the remaining helper functions: draw_symbols(), is_board_full(), is_winner(), make_move(), player_move(), ai_move(), check_game_over(), draw_winner(), draw_reset_button(), and reset_game().
## Helper functions
def draw_symbols():
for x in range(3):
for y in range(3):
symbol = board[x][y]
if symbol == PLAYER_SYMBOL:
color = PLAYER_COLOR
elif symbol == AI_SYMBOL:
color = AI_COLOR
else:
color = EMPTY_COLOR
if symbol != "":
pygame.draw.circle(
win,
color,
(x * CELL_SIZE + CELL_SIZE // 2, y * CELL_SIZE + CELL_SIZE // 2),
CELL_SIZE // 2 - 10,
2,
)
def is_board_full():
for row in board:
if "" in row:
return False
return True
def is_winner(symbol):
for row in board:
if all(cell == symbol for cell in row):
return True
for col in range(3):
if all(board[row][col] == symbol for row in range(3)):
return True
if all(board[i][i] == symbol for i in range(3)):
return True
if all(board[i][2 - i] == symbol for i in range(3)):
return True
return False
def make_move(x, y, symbol):
if board[x][y] == "":
board[x][y] = symbol
return True
return False
def player_move():
global turn
mouse_pos = pygame.mouse.get_pos()
cell_x = mouse_pos[0] // CELL_SIZE
cell_y = mouse_pos[1] // CELL_SIZE
if make_move(cell_x, cell_y, PLAYER_SYMBOL):
turn = "ai"
def ai_move():
global turn
empty_cells = []
for x in range(3):
for y in range(3):
if board[x][y] == "":
empty_cells.append((x, y))
if empty_cells:
x, y = random.choice(empty_cells)
make_move(x, y, AI_SYMBOL)
turn = "player"
def check_game_over():
global game_over, winner
if is_winner(PLAYER_SYMBOL):
game_over = True
return "player"
elif is_winner(AI_SYMBOL):
game_over = True
return "ai"
elif is_board_full():
game_over = True
return "tie"
return None
def draw_winner():
font = pygame.font.Font(None, 50)
if winner == "player":
text = font.render("Player Wins!", True, PLAYER_COLOR)
elif winner == "ai":
text = font.render("AI Wins!", True, AI_COLOR)
else:
text = font.render("It's a Tie!", True, (255, 255, 255))
text_rect = text.get_rect(center=(WIDTH // 2, HEIGHT // 3))
win.blit(text, text_rect)
def draw_reset_button():
pygame.draw.rect(win, BUTTON_COLOR, reset_button_rect)
button_text = BUTTON_FONT.render("Reset", True, BUTTON_TEXT_COLOR)
button_text_rect = button_text.get_rect(center=reset_button_rect.center)
win.blit(button_text, button_text_rect)
def reset_game():
global board, turn, game_over, winner
board = [["" for _ in range(3)] for _ in range(3)]
turn = "player"
game_over = False
winner = None
In above code, the draw_symbols() function will draw the symbols on the board. The is_board_full() function will check if the board is full. The is_winner() function will check if the given symbol has won the game. The make_move() function will make a move on the board. The player_move() function will handle the player's move. The ai_move() function will handle the AI's move. The check_game_over() function will check if the game is over. The draw_winner() function will draw the winner message. The draw_reset_button() function will draw the reset button. The reset_game() function will reset the game.
Fill in the remaining code
Finally, fill in the remaining code inside the main game loop to call the helper functions at the appropriate places. This includes calling the draw_board() and draw_symbols() functions to draw the game board and symbols, calling the check_game_over() function to check if the game is over, and calling the draw_winner() and draw_reset_button() functions to draw the winner message and reset button, respectively.
## Main game loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
if reset_button_rect.collidepoint(event.pos):
reset_game()
elif not game_over and turn == "player":
player_move()
if not game_over and turn == "ai":
ai_move()
winner = check_game_over()
draw_board()
draw_symbols()
if game_over:
draw_winner()
draw_reset_button()
pygame.display.flip()
## Quit the game
pygame.quit()
Run the game using the following command:
python tic_tac_toe.py

Summary
Congratulations! You have successfully created a Tic-Tac-Toe game using Pygame. In this project, you learned how to set up the game window, draw the game board, handle player and AI moves, and determine the winner. You also learned how to implement helper functions to simplify the code and make it more modular.



