How to Make a Checkers Game with Python

Hichem MGHichem MG
5 min read

Creating a Checkers game in Python is an exciting project that combines several important programming concepts, including object-oriented programming, game logic, and graphical user interfaces (GUIs).

For this guide, we'll use the popular Pygame library, which is well-suited for creating 2D games. Pygame provides the tools needed to manage game windows, draw shapes and images, handle user input, and manage the game loop.

Prerequisites

Before we begin, ensure you have Python and Pygame installed on your system. You can install Pygame using pip:

pip install pygame

Step 1: Setting Up the Project Structure

First, create a project directory for your Checkers game. Inside this directory, create the following files:

  • main.py: The main game file where the game loop will reside.

  • constants.py: A file to store all constant values, such as colors, dimensions, etc.

  • board.py: A file to manage the game board.

  • piece.py: A file to manage the individual pieces.

  • game.py: A file to manage the game logic and state.

Step 2: Defining Constants

In constants.py, define the constants for your game. These constants will include colors, dimensions, and other settings.

# constants.py
import pygame

# Screen dimensions
WIDTH, HEIGHT = 800, 800
ROWS, COLS = 8, 8
SQUARE_SIZE = WIDTH // COLS

# Colors
RED = (255, 0, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BLUE = (0, 0, 255)
GREY = (128, 128, 128)

# Piece
CROWN = pygame.transform.scale(pygame.image.load('assets/crown.png'), (44, 25))

Step 3: Creating the Game Board

In board.py, create a class to represent the game board. This class will handle drawing the board and managing the state of the pieces.

# board.py
import pygame
from .constants import *

class Board:
    def __init__(self):
        self.board = []
        self.create_board()

    def draw_squares(self, win):
        win.fill(BLACK)
        for row in range(ROWS):
            for col in range(row % 2, COLS, 2):
                pygame.draw.rect(win, RED, (row*SQUARE_SIZE, col*SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE))

    def create_board(self):
        for row in range(ROWS):
            self.board.append([])
            for col in range(COLS):
                if col % 2 == ((row + 1) % 2):
                    if row < 3:
                        self.board[row].append(Piece(row, col, WHITE))
                    elif row > 4:
                        self.board[row].append(Piece(row, col, RED))
                    else:
                        self.board[row].append(0)
                else:
                    self.board[row].append(0)

    def draw(self, win):
        self.draw_squares(win)
        for row in range(ROWS):
            for col in range(COLS):
                piece = self.board[row][col]
                if piece != 0:
                    piece.draw(win)

Step 4: Creating the Pieces

In piece.py, create a class to represent individual pieces. This class will handle drawing the pieces and managing their state.

# piece.py
import pygame
from .constants import *

class Piece:
    PADDING = 15
    OUTLINE = 2

    def __init__(self, row, col, color):
        self.row = row
        self.col = col
        self.color = color
        self.king = False

        self.x = 0
        self.y = 0
        self.calc_pos()

    def calc_pos(self):
        self.x = SQUARE_SIZE * self.col + SQUARE_SIZE // 2
        self.y = SQUARE_SIZE * self.row + SQUARE_SIZE // 2

    def make_king(self):
        self.king = True

    def draw(self, win):
        radius = SQUARE_SIZE//2 - self.PADDING
        pygame.draw.circle(win, GREY, (self.x, self.y), radius + self.OUTLINE)
        pygame.draw.circle(win, self.color, (self.x, self.y), radius)
        if self.king:
            win.blit(CROWN, (self.x - CROWN.get_width()//2, self.y - CROWN.get_height()//2))

    def move(self, row, col):
        self.row = row
        self.col = col
        self.calc_pos()

Step 5: Managing Game Logic

In game.py, create a class to manage the game logic, including updating the state of the board, moving pieces, and handling captures.

# game.py
import pygame
from .constants import *
from .board import Board

class Game:
    def __init__(self, win):
        self._init()
        self.win = win

    def _init(self):
        self.selected = None
        self.board = Board()
        self.turn = RED
        self.valid_moves = {}

    def update(self):
        self.board.draw(self.win)
        self.draw_valid_moves(self.valid_moves)
        pygame.display.update()

    def reset(self):
        self._init()

    def select(self, row, col):
        if self.selected:
            result = self._move(row, col)
            if not result:
                self.selected = None
                self.select(row, col)

        piece = self.board.get_piece(row, col)
        if piece != 0 and piece.color == self.turn:
            self.selected = piece
            self.valid_moves = self.board.get_valid_moves(piece)
            return True

        return False

    def _move(self, row, col):
        piece = self.board.get_piece(row, col)
        if self.selected and piece == 0 and (row, col) in self.valid_moves:
            self.board.move(self.selected, row, col)
            skipped = self.valid_moves[(row, col)]
            if skipped:
                self.board.remove(skipped)
            self.change_turn()
        else:
            return False

        return True

    def draw_valid_moves(self, moves):
        for move in moves:
            row, col = move
            pygame.draw.circle(self.win, BLUE, (col * SQUARE_SIZE + SQUARE_SIZE//2, row * SQUARE_SIZE + SQUARE_SIZE//2), 15)

    def change_turn(self):
        self.valid_moves = {}
        if self.turn == RED:
            self.turn = WHITE
        else:
            self.turn = RED

Step 6: Creating the Main Game Loop

In main.py, create the main game loop that initializes the game and handles user input.

# main.py
import pygame
from .constants import *
from .game import Game

FPS = 60

WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Checkers')

def get_row_col_from_mouse(pos):
    x, y = pos
    row = y // SQUARE_SIZE
    col = x // SQUARE_SIZE
    return row, col

def main():
    run = True
    clock = pygame.time.Clock()
    game = Game(WIN)

    while run:
        clock.tick(FPS)

        if game.winner() != None:
            print(game.winner())
            run = False

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

            if event.type == pygame.MOUSEBUTTONDOWN:
                pos = pygame.mouse.get_pos()
                row, col = get_row_col_from_mouse(pos)
                game.select(row, col)

        game.update()

    pygame.quit()

main()

Conclusion

With the above steps, you should have a basic but functional Checkers game. The game board and pieces are drawn, and you can select and move pieces according to the rules of Checkers. The game logic handles piece movement, turn changes, and capturing pieces.

This guide provides a solid foundation for your Checkers game. You can expand on this by adding more features such as AI opponents, a better user interface, and additional game rules.

Feel free to modify and enhance the code to suit your needs, and happy coding!

0
Subscribe to my newsletter

Read articles from Hichem MG directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Hichem MG
Hichem MG

Python dev, coding enthusiast, problem solver. Passionate about clean code and tech innovation.