Learn Algorithms Through Chess Puzzles
SkillVeris Team
Content Team

Chess problems are algorithmic classics because they're constrained, well-defined, and familiar โ solving them in Python makes algorithm fundamentals click.
In this guide, you'll learn:
- The knight's shortest path teaches Breadth-First Search, which guarantees the shortest path in a graph.
- The N-Queens problem teaches backtracking โ the try, recurse, and undo pattern for constraint satisfaction.
- Generating a sliding piece's legal moves teaches recursion, where each step is identical to the last.
- Minimax teaches game-tree search by assuming optimal play from both sides, and alpha-beta pruning skips branches that can't change the result.
1Why Chess Teaches Algorithms
Chess has been intertwined with computer science since Alan Turing proposed a paper chess player in 1950. The reason is structural: chess problems are well-defined, constrained, and finite โ exactly the conditions where algorithms shine. The board is 64 squares, the rules are fixed, and the goal is clear.
This makes chess a perfect laboratory for learning search, recursion, and optimisation without the messiness of real-world data. Every algorithm in this guide maps to a classic computer science topic, but the chess context makes the abstraction concrete.
2Representing a Chessboard in Python
Before any algorithm, you need a board representation. An 8x8 2D list is intuitive for learning, with each square addressed as a (row, col) tuple. The KNIGHT_DELTAS list captures all eight L-shaped knight moves.
Board and Knight Moves
A 2D list plus a helper to keep moves on the board.
# An 8x8 board as a 2D list
# 0 = empty, positive = white piece, negative = black piece
board = [[0] * 8 for _ in range(8)]
# A square is a (row, col) tuple, both 0-7
# (0,0) = a8 (top-left), (7,7) = h1 (bottom-right)
def on_board(r: int, c: int) -> bool:
return 0 <= r < 8 and 0 <= c < 8
# Knight moves: all 8 L-shapes
KNIGHT_DELTAS = [
(-2,-1), (-2,1), (-1,-2), (-1,2),
( 1,-2), ( 1,2), ( 2,-1), ( 2,1),
]3BFS: Knight's Shortest Path
Problem: find the minimum number of moves for a knight to travel from square A to square B. This is the classic Breadth-First Search (BFS) on a graph where each square is a node and knight moves are edges.
BFS guarantees the shortest path because it explores all positions reachable in one move before any reachable in two. The queue processes nodes level by level, and the visited set prevents revisiting squares, keeping time complexity O(64) = O(1) for a chessboard.

Knight Shortest Path with BFS
A deque processes positions level by level.
from collections import deque
def knight_shortest_path(start: tuple, end: tuple) -> int:
if start == end:
return 0
visited = {start}
queue = deque([(start, 0)]) # (position, moves_taken)
while queue:
(r, c), moves = queue.popleft()
for dr, dc in KNIGHT_DELTAS:
nr, nc = r + dr, c + dc
if not on_board(nr, nc):
continue
if (nr, nc) == end:
return moves + 1
if (nr, nc) not in visited:
visited.add((nr, nc))
queue.append(((nr, nc), moves + 1))
return -1 # unreachable (never happens on a standard board)
print(knight_shortest_path((0, 0), (7, 7))) # 6 moves
print(knight_shortest_path((0, 0), (1, 1))) # 4 moves4The N-Queens Problem: Backtracking
Problem: place 8 queens on an 8x8 board such that no two queens attack each other (no shared row, column, or diagonal). This is the classic backtracking problem.
Backtracking is the pattern: try an option, recurse to see if it leads to a solution, undo if not. The key is the queens.pop() line โ it's what makes the algorithm "backtrack" to try the next column. This same pattern solves Sudoku, crossword filling, and constraint satisfaction problems.
Solving N-Queens
Place a queen, recurse, and undo on failure.
def solve_n_queens(n: int = 8) -> list:
solutions = []
queens = [] # queens[row] = column of queen in that row
def is_safe(row: int, col: int) -> bool:
for r, c in enumerate(queens):
if c == col: return False # same column
if abs(r - row) == abs(c - col): return False # same diagonal
return True
def backtrack(row: int):
if row == n:
solutions.append(queens[:]) # found a valid placement
return
for col in range(n):
if is_safe(row, col):
queens.append(col) # place queen
backtrack(row + 1) # recurse to next row
queens.pop() # UNDO (backtrack)
backtrack(0)
return solutions
solutions = solve_n_queens(8)
print(f"Found {len(solutions)} solutions") # 925Recursion: Generating All Legal Moves
Recursion is natural for sliding pieces because each sliding step is identical to the previous one โ the function calls itself with the next square. The recursive slide function continues in a direction until it hits the board edge or a piece.
Rook Moves via Recursion
Slide recursively until blocked, capturing enemy pieces.
def rook_moves(board: list, r: int, c: int) -> list:
# A rook moves any number of squares horizontally or vertically
moves = []
for direction in [(-1,0),(1,0),(0,-1),(0,1)]:
dr, dc = direction
def slide(nr, nc):
if not on_board(nr, nc):
return
if board[nr][nc] != 0:
if board[nr][nc] < 0: # enemy piece: capture, then stop
moves.append((nr, nc))
return
moves.append((nr, nc))
slide(nr + dr, nc + dc) # recurse: continue sliding
slide(r + dr, c + dc)
return moves6Minimax: Game Tree Search
Minimax is how game-playing AI works. The idea: your opponent plays optimally against you, so assume they'll pick the move that minimises your score, while you pick the move that maximises it.
Minimax is pure recursion: search the tree to a given depth, evaluate the leaves, and bubble scores back up. White maximises; Black minimises. At depth 3, the AI considers every possible response to every possible move three levels deep.

Evaluate and Minimax
A material evaluation function plus the recursive search.
def evaluate(board: list) -> int:
# Material count: positive = white advantage
piece_values = {1:1, 2:3, 3:3, 4:5, 5:9} # pawn,knight,bishop,rook,queen
score = 0
for row in board:
for piece in row:
if piece > 0: score += piece_values.get(piece, 0)
if piece < 0: score -= piece_values.get(abs(piece), 0)
return score
def minimax(board: list, depth: int, is_white: bool) -> int:
if depth == 0:
return evaluate(board) # base case: evaluate leaf node
best = -9999 if is_white else 9999
for move in generate_all_moves(board, is_white):
make_move(board, move)
score = minimax(board, depth - 1, not is_white)
undo_move(board, move)
if is_white: best = max(best, score)
else: best = min(best, score)
return best7Alpha-Beta Pruning
Minimax is correct but slow โ it searches every branch. Alpha-beta pruning skips branches that can't affect the final result.
Alpha-beta can reduce the number of nodes searched from O(b^d) to O(b^(d/2)) โ effectively doubling the search depth for the same computation. This is how chess engines search 10-20 moves deep.
Minimax with Alpha-Beta
Cut-offs prune branches the opponent would never allow.
def minimax_ab(board, depth, alpha, beta, is_white):
if depth == 0: return evaluate(board)
for move in generate_all_moves(board, is_white):
make_move(board, move)
score = minimax_ab(board, depth-1, alpha, beta, not is_white)
undo_move(board, move)
if is_white:
alpha = max(alpha, score)
if alpha >= beta: break # beta cut-off: opponent won't allow this
else:
beta = min(beta, score)
if beta <= alpha: break # alpha cut-off
return alpha if is_white else beta8Sorting Chess Games by Rating
Modelling games with a dataclass makes sorting and filtering clean. Use sorted() with a key function to order games by rating, and combine it with a comprehension to filter for decisive results.
Dataclass and Sorting
Key functions drive the sort order.
from dataclasses import dataclass
@dataclass
class Game:
white_player: str
black_player: str
white_elo: int
result: str # "1-0", "0-1", "1/2-1/2"
games = [
Game("Magnus", "Hikaru", 2853, "1-0"),
Game("Alireza", "Pragg", 2788, "0-1"),
Game("Gukesh", "Nepo", 2794, "1/2-1/2"),
]
# Sort by white Elo, descending
sorted_games = sorted(games, key=lambda g: g.white_elo, reverse=True)
# Filter only decisive games, sorted by Elo
decisive = sorted(
[g for g in games if g.result != "1/2-1/2"],
key=lambda g: g.white_elo,
reverse=True
)9Closing Thoughts on CS Through Chess
Each problem in this guide reveals a general algorithm pattern that transfers far beyond chess.
- Knight shortest path โ BFS โ transfers to shortest path and social network distance.
- N-Queens โ Backtracking โ transfers to Sudoku, scheduling, and constraint satisfaction problems.
- Move generation โ Recursion โ transfers to tree traversal, parsing, and fractals.
- Game AI โ Minimax โ transfers to decision trees and adversarial search.
10Extending These Projects
Once the core algorithms click, extend them into larger projects that combine several techniques.
- Implement the full knight's tour (visiting every square exactly once) using backtracking with Warnsdorff's heuristic.
- Build a complete chess engine that plays legal games: piece generation for all six piece types, check/checkmate detection, and a simple minimax player.
- Visualise the N-Queens solutions as an animation in Python using turtle or matplotlib.
- Build a chess puzzle solver: given a position and "White to move and win in 2," use minimax to find the solution.
11What You Actually Learned
If you coded along with this guide, you practised BFS with a deque, recursion with backtracking, tree search with minimax, alpha-beta optimisation, dataclasses, sorting with key functions, and representing structured data as 2D arrays.
These are not chess skills; they are computer science skills, demonstrated on a board game that makes the constraints clear.
12Key Takeaways
The patterns here are the building blocks of search and optimisation across computer science.
- BFS (using a queue) guarantees shortest paths; use it for minimum-move problems.
- Backtracking is "try + recurse + undo" โ the pattern for constraint satisfaction problems.
- Minimax evaluates game trees by assuming optimal play from both sides; alpha-beta skips irrelevant branches.
- Chess problems teach algorithms because they're well-defined, finite, and visually intuitive.
13What to Learn Next
Deepen your algorithms knowledge with these next steps.
- Learn React Through Chess (Clock) โ chess from a frontend angle.
- Machine Learning for Beginners โ modern chess engines use neural networks, not just minimax.
- Python OOP โ model chess pieces and the board as classes for a cleaner implementation.
14Frequently Asked Questions
Do I need to know chess to benefit from this guide? Basic familiarity helps (knowing how pieces move), but the code works regardless of chess expertise. The algorithms โ BFS, backtracking, minimax โ are what matter. If you don't know chess, the knight's L-move and queen's diagonal movement are the only rules you need for most of these examples.
Is this how real chess engines like Stockfish work? The fundamentals are the same: minimax with alpha-beta is still the core of all major chess engines. Modern engines like Stockfish add hundreds of heuristics (null move pruning, late move reductions, aspiration windows) and a neural network evaluation function. The minimax in this guide is the conceptual foundation of all of them.
What data structure is best for representing a chess board? A 2D list (as used here) is intuitive for learning. Production engines use bitboards โ 64-bit integers where each bit represents a square. Bitboards allow move generation using bitwise operations, which is orders of magnitude faster. For learning, the 2D list is clearer; for performance, bitboards are the standard.
Can I use this approach to learn other algorithms? Absolutely. Football data teaches SQL aggregation. Music teaches audio signal processing. Cooking teaches constraint satisfaction (recipe substitution). Any domain you care about has structures and constraints that map onto computer science concepts. The motivation to understand the domain drives the effort to understand the algorithm.
Related Reading
Get The Print Version
Download a PDF of this article for offline reading.
About the Publisher
SkillVeris Team
Content Team
We believe the best way to learn tech is through what you already love โ sports, music, photography, and more.
View all postsRelated Posts
Never miss an update
Get the latest tutorials and guides delivered to your inbox.
No spam. Unsubscribe anytime.