Game Programming in Python. Part 2.

Welcome back to our Python game programming series! In Part 1, we covered the basics of pygame and created a simple interactive window. In this second part, we’ll build a complete Tic-Tac-Toe game with a graphical interface, turn management, and win detection.

What We’ll Build

Our Tic-Tac-Toe game will include:

  • A graphical 3×3 game board drawn with pygame
  • Two-player turn management (X and O)
  • Click detection to place marks
  • Win detection (rows, columns, diagonals)
  • Draw detection
  • Game reset functionality

Setting Up

Make sure you have pygame installed: pip install pygame

The Game Structure

import pygame
import sys

# Constants
WINDOW_SIZE = 600
BOARD_SIZE = 3
CELL_SIZE = WINDOW_SIZE // BOARD_SIZE
LINE_WIDTH = 5
CIRCLE_RADIUS = CELL_SIZE // 3
CIRCLE_WIDTH = 15
CROSS_WIDTH = 25
SPACE = CELL_SIZE // 4

# Colors
BG_COLOR = (28, 170, 156)
LINE_COLOR = (23, 145, 135)
CIRCLE_COLOR = (239, 231, 200)
CROSS_COLOR = (66, 66, 66)

pygame.init()
screen = pygame.display.set_mode((WINDOW_SIZE, WINDOW_SIZE))
pygame.display.set_caption("Tic Tac Toe")
screen.fill(BG_COLOR)

Board Logic

board = [[None] * BOARD_SIZE for _ in range(BOARD_SIZE)]

def draw_lines():
    # Horizontal lines
    for i in range(1, BOARD_SIZE):
        pygame.draw.line(screen, LINE_COLOR, (0, i * CELL_SIZE), (WINDOW_SIZE, i * CELL_SIZE), LINE_WIDTH)
    # Vertical lines
    for i in range(1, BOARD_SIZE):
        pygame.draw.line(screen, LINE_COLOR, (i * CELL_SIZE, 0), (i * CELL_SIZE, WINDOW_SIZE), LINE_WIDTH)

def draw_marks():
    for row in range(BOARD_SIZE):
        for col in range(BOARD_SIZE):
            if board[row][col] == 'O':
                center = (col * CELL_SIZE + CELL_SIZE // 2, row * CELL_SIZE + CELL_SIZE // 2)
                pygame.draw.circle(screen, CIRCLE_COLOR, center, CIRCLE_RADIUS, CIRCLE_WIDTH)
            elif board[row][col] == 'X':
                start1 = (col * CELL_SIZE + SPACE, row * CELL_SIZE + SPACE)
                end1 = (col * CELL_SIZE + CELL_SIZE - SPACE, row * CELL_SIZE + CELL_SIZE - SPACE)
                start2 = (col * CELL_SIZE + CELL_SIZE - SPACE, row * CELL_SIZE + SPACE)
                end2 = (col * CELL_SIZE + SPACE, row * CELL_SIZE + CELL_SIZE - SPACE)
                pygame.draw.line(screen, CROSS_COLOR, start1, end1, CROSS_WIDTH)
                pygame.draw.line(screen, CROSS_COLOR, start2, end2, CROSS_WIDTH)

Win Detection

def check_winner(player):
    # Check rows
    for row in range(BOARD_SIZE):
        if all(board[row][col] == player for col in range(BOARD_SIZE)):
            return True
    # Check columns
    for col in range(BOARD_SIZE):
        if all(board[row][col] == player for row in range(BOARD_SIZE)):
            return True
    # Check diagonals
    if all(board[i][i] == player for i in range(BOARD_SIZE)):
        return True
    if all(board[i][BOARD_SIZE-1-i] == player for i in range(BOARD_SIZE)):
        return True
    return False

def is_board_full():
    return all(board[row][col] is not None 
               for row in range(BOARD_SIZE) 
               for col in range(BOARD_SIZE))

Main Game Loop

def main():
    current_player = 'X'
    game_over = False
    
    draw_lines()
    
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            
            if event.type == pygame.MOUSEBUTTONDOWN and not game_over:
                mouseX, mouseY = event.pos
                clicked_row = mouseY // CELL_SIZE
                clicked_col = mouseX // CELL_SIZE
                
                if board[clicked_row][clicked_col] is None:
                    board[clicked_row][clicked_col] = current_player
                    
                    if check_winner(current_player):
                        print(f"Player {current_player} wins!")
                        game_over = True
                    elif is_board_full():
                        print("It's a draw!")
                        game_over = True
                    else:
                        current_player = 'O' if current_player == 'X' else 'X'
            
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r:  # Reset game
                    for row in range(BOARD_SIZE):
                        for col in range(BOARD_SIZE):
                            board[row][col] = None
                    game_over = False
                    current_player = 'X'
                    screen.fill(BG_COLOR)
                    draw_lines()
        
        screen.fill(BG_COLOR)
        draw_lines()
        draw_marks()
        pygame.display.update()

main()

What You’ve Learned

By building this game, you’ve practiced:

  • Drawing shapes and lines with pygame
  • Handling mouse click events
  • Mapping screen coordinates to game grid positions
  • Implementing game logic (win detection, turn management)
  • Game state management

Extensions to Try

Once you have the basic game working, try these improvements:

  • Add a score counter for multiple rounds
  • Implement a simple AI opponent
  • Add sound effects
  • Display the winner with a highlighted winning line

Happy coding!

By admin

Leave a Reply

Your email address will not be published. Required fields are marked *