Table of Contents
- Introduction
- Prerequisites
- Setup
- Creating the Board
- Placing the Pieces
- Moving the Pieces
- Validating Moves
- Capturing Opponent’s Pieces
- Game Loop
- Conclusion
Introduction
In this tutorial, we will be creating a checkers game using Python. Checkers is a classic board game played between two players on an 8x8 board. The goal is to capture all of your opponent’s pieces or block them from making any more moves. By the end of this tutorial, you will have a working checkers game that you can play against a friend or computer opponent.
Prerequisites
To follow along with this tutorial, you should have a basic understanding of Python programming concepts such as variables, functions, loops, and conditionals. Familiarity with object-oriented programming (OOP) will also be helpful.
Setup
Before we begin coding, let’s set up our development environment. We will be using Python 3 for this project.
-
Install Python 3 on your system if you haven’t already. You can download it from the official Python website: https://www.python.org/downloads/
-
Create a new directory for your checkers game project.
-
Open your terminal or command prompt and navigate to the project directory.
-
Create a virtual environment by running the following command:
python3 -m venv venv
-
Activate the virtual environment:
-
On macOS and Linux:
source venv/bin/activate
-
On Windows:
venv\Scripts\activate
-
-
Now, we can proceed with creating our checkers game!
Creating the Board
Let’s start by creating the game board. We will represent the board using a 2D list, where each element of the list represents a square on the board. We will use the following symbols to represent different types of squares:
.
for empty squaresB
for black piecesW
for white pieces
Create a new file called checkers.py
and add the following code:
```python
# checkers.py
class CheckersGame:
def __init__(self):
self.board = [['.' for _ in range(8)] for _ in range(8)]
def display_board(self):
for row in self.board:
print(' '.join(row))
``` Here, we define a `CheckersGame` class with an `__init__` method that initializes the game board as an 8x8 grid with empty squares.
The display_board
method prints the current state of the board to the console.
Let’s write some code to test our board creation. Add the following code to the bottom of checkers.py
:
```python
# checkers.py
if __name__ == '__main__':
game = CheckersGame()
game.display_board()
``` Save the file and run it with the following command:
```bash
python checkers.py
``` You should see an empty 8x8 board displayed in the console.
Placing the Pieces
Now that we have our game board, let’s add the ability to place the pieces on the board. Black pieces will be represented by B
and white pieces by W
. We will define a starting setup where each player has 12 pieces.
Modify the __init__
method of the CheckersGame
class as follows:
```python
# checkers.py
class CheckersGame:
def __init__(self):
self.board = [['.' for _ in range(8)] for _ in range(8)]
self.place_pieces()
def display_board(self):
for row in self.board:
print(' '.join(row))
def place_pieces(self):
for row in range(3):
for col in range(8):
# Place black pieces in the top three rows
if (row + col) % 2 == 1:
self.board[row][col] = 'B'
for row in range(5, 8):
for col in range(8):
# Place white pieces in the bottom three rows
if (row + col) % 2 == 1:
self.board[row][col] = 'W'
``` We have added a new method `place_pieces` that places the black and white pieces on the board according to the starting setup. The black pieces are placed in the top three rows, and the white pieces are placed in the bottom three rows.
Let’s run the game again to see the pieces on the board:
bash
python checkers.py
You should now see the black and white pieces arranged in their starting positions on the board.
Moving the Pieces
Now, let’s implement the ability to move the pieces on the board. We will allow players to move their pieces diagonally forward one square at a time. We will represent the pieces with the following symbols:
b
for black piecesw
for white pieces
Modify the CheckersGame
class as follows:
```python
# checkers.py
class CheckersGame:
def __init__(self):
self.board = [['.' for _ in range(8)] for _ in range(8)]
self.place_pieces()
self.current_player = 'B'
def display_board(self):
for row in self.board:
print(' '.join(row))
def place_pieces(self):
for row in range(3):
for col in range(8):
# Place black pieces in the top three rows
if (row + col) % 2 == 1:
self.board[row][col] = 'B'
for row in range(5, 8):
for col in range(8):
# Place white pieces in the bottom three rows
if (row + col) % 2 == 1:
self.board[row][col] = 'W'
def make_move(self, start_pos, end_pos):
start_row, start_col = start_pos
end_row, end_col = end_pos
piece = self.board[start_row][start_col]
if piece == '.':
print("No piece at the starting position.")
return
if self.current_player == 'B' and piece != 'b':
print("Invalid move. It's not your turn.")
return
if self.current_player == 'W' and piece != 'w':
print("Invalid move. It's not your turn.")
return
if piece == 'b' and end_row <= start_row:
print("Invalid move. Pieces can only move forward.")
return
if piece == 'w' and end_row >= start_row:
print("Invalid move. Pieces can only move forward.")
return
if abs(start_row - end_row) != 1 or abs(start_col - end_col) != 1:
print("Invalid move. Pieces can only move diagonally one square at a time.")
return
self.board[start_row][start_col] = '.'
self.board[end_row][end_col] = piece
self.current_player = 'W' if self.current_player == 'B' else 'B'
``` We have added a `make_move` method to the `CheckersGame` class. This method takes two parameters: `start_pos` and `end_pos`, which represent the starting and ending positions of the move. The method performs several checks to validate the move:
- It checks if there is a piece at the starting position.
- It checks if it’s the current player’s turn.
- It checks if the piece is moving in the correct direction.
- It checks if the move is diagonal and one square at a time.
If all the checks pass, the method updates the board to reflect the move and switches the current player.
To test the movement of pieces, add the following code to the bottom of checkers.py
:
```python
# checkers.py
if __name__ == '__main__':
game = CheckersGame()
game.display_board()
print("Black player's move:")
game.make_move((2, 1), (3, 2))
game.display_board()
print("White player's move:")
game.make_move((5, 2), (4, 3))
game.display_board()
``` Save the file and run it again:
```bash
python checkers.py
``` You should see the board before and after each move.
Validating Moves
Currently, our move validation is limited to basic checks. We need to implement additional logic to handle more complex moves such as capturing opponent’s pieces and enforcing mandatory captures.
We will update the make_move
method to handle capturing opponent’s pieces. If a piece can capture an opponent’s piece, the move will be considered valid. We will use the following symbols to represent captured pieces:
B
for captured black piecesW
for captured white pieces
Modify the CheckersGame
class as follows:
```python
# checkers.py
class CheckersGame:
def __init__(self):
self.board = [['.' for _ in range(8)] for _ in range(8)]
self.place_pieces()
self.current_player = 'B'
def display_board(self):
for row in self.board:
print(' '.join(row))
def place_pieces(self):
for row in range(3):
for col in range(8):
# Place black pieces in the top three rows
if (row + col) % 2 == 1:
self.board[row][col] = 'B'
for row in range(5, 8):
for col in range(8):
# Place white pieces in the bottom three rows
if (row + col) % 2 == 1:
self.board[row][col] = 'W'
def make_move(self, start_pos, end_pos):
start_row, start_col = start_pos
end_row, end_col = end_pos
piece = self.board[start_row][start_col]
if piece == '.':
print("No piece at the starting position.")
return
if self.current_player == 'B' and piece != 'b':
print("Invalid move. It's not your turn.")
return
if self.current_player == 'W' and piece != 'w':
print("Invalid move. It's not your turn.")
return
if piece == 'b' and end_row <= start_row:
print("Invalid move. Pieces can only move forward.")
return
if piece == 'w' and end_row >= start_row:
print("Invalid move. Pieces can only move forward.")
return
if abs(start_row - end_row) != 1 or abs(start_col - end_col) != 1:
# Check for capture
if abs(start_row - end_row) == 2 and abs(start_col - end_col) == 2:
middle_row = (start_row + end_row) // 2
middle_col = (start_col + end_col) // 2
middle_piece = self.board[middle_row][middle_col]
if middle_piece != '.' and piece.lower() != middle_piece.lower():
# Capture the opponent's piece
opponent_piece = 'B' if middle_piece == 'W' else 'W'
self.board[middle_row][middle_col] = opponent_piece
self.board[start_row][start_col] = '.'
self.board[end_row][end_col] = piece
self.current_player = 'W' if self.current_player == 'B' else 'B'
return
print("Invalid move. Pieces can only move diagonally one square at a time.")
return
self.board[start_row][start_col] = '.'
self.board[end_row][end_col] = piece
self.current_player = 'W' if self.current_player == 'B' else 'B'
``` We have added a check for capturing an opponent's piece. If the move is diagonal and two squares away in both row and column, we calculate the position of the middle square and check if there is an opponent's piece in that square. If there is, we capture the piece by changing it to the corresponding opponent's piece.
Let’s test the capturing of opponent’s pieces. Update the code at the bottom of checkers.py
as follows:
```python
# checkers.py
if __name__ == '__main__':
game = CheckersGame()
game.display_board()
print("Black player's move:")
game.make_move((2, 1), (3, 2))
game.display_board()
print("White player's move (capturing):")
game.make_move((5, 2), (3, 0))
game.display_board()
``` Save the file and run it again:
```bash
python checkers.py
``` You should see the captured piece on the board after the white player's move.
Game Loop
Now that we have implemented the basic gameplay mechanics, let’s add a game loop that allows players to take turns until the game is over. We will also add logic to check if a player has won the game.
Modify the CheckersGame
class as follows:
```python
# checkers.py
class CheckersGame:
def __init__(self):
self.board = [['.' for _ in range(8)] for _ in range(8)]
self.place_pieces()
self.current_player = 'B'
def display_board(self):
for row in self.board:
print(' '.join(row))
def place_pieces(self):
for row in range(3):
for col in range(8):
# Place black pieces in the top three rows
if (row + col) % 2 == 1:
self.board[row][col] = 'B'
for row in range(5, 8):
for col in range(8):
# Place white pieces in the bottom three rows
if (row + col) % 2 == 1:
self.board[row][col] = 'W'
def make_move(self, start_pos, end_pos):
# move logic...
def get_winner(self):
black_pieces = 0
white_pieces = 0
for row in range(8):
for col in range(8):
if self.board[row][col].lower() == 'b':
black_pieces += 1
elif self.board[row][col].lower() == 'w':
white_pieces += 1
if black_pieces == 0:
return 'White'
if white_pieces == 0:
return 'Black'
return None
def play_game(self):
while True:
self.display_board()
print("Current player:", "Black" if self.current_player == 'B' else "White")
start_pos = tuple(map(int, input("Enter the starting position (row, col): ").split(',')))
end_pos = tuple(map(int, input("Enter the ending position (row, col): ").split(',')))
self.make_move(start_pos, end_pos)
winner = self.get_winner()
if winner:
print("Game over. The winner is:", winner)
break
``` We have added a `get_winner` method that counts the remaining black and white pieces on the board and determines the winner based on the counts. If one of the players has no remaining pieces, the other player is declared the winner. If there are pieces of both players remaining, the game continues.
The play_game
method implements the game loop. It displays the current state of the board, prompts the current player for their move, and checks for a winner after each move. If there is a winner, the loop breaks and the winner is announced.
To start the game, update the code at the bottom of checkers.py
as follows:
```python
# check