Kelick Tech Hub

Build, learn & keep up — tech, Linux & sports news included.

C++ Sudoku Solver Project

Intermediate•1–2 days•recursion, backtracking, 2D arrays

Feed it any Sudoku puzzle; backtracking finds the solution in milliseconds.

Share on X

What you will build

Give the program a half-empty grid and it fills in the rest — by trying a number, recursing, and undoing the guess when it leads nowhere. Backtracking is one of the most powerful ideas in programming, and Sudoku is its friendliest showcase.

What you will learn

Feature checklist

Starter code

#include <array>
#include <iostream>

using Grid = std::array<std::array<int, 9>, 9>;

bool ok(const Grid& g, int r, int c, int v) {
    for (int i = 0; i < 9; ++i)
        if (g[r][i] == v || g[i][c] == v) return false;
    int br = r - r % 3, bc = c - c % 3;         // box origin
    for (int i = 0; i < 3; ++i)
        for (int j = 0; j < 3; ++j)
            if (g[br + i][bc + j] == v) return false;
    return true;
}

bool solve(Grid& g) {
    for (int r = 0; r < 9; ++r)
        for (int c = 0; c < 9; ++c)
            if (g[r][c] == 0) {
                for (int v = 1; v <= 9; ++v)
                    if (ok(g, r, c, v)) {
                        g[r][c] = v;
                        if (solve(g)) return true;
                        g[r][c] = 0;         // backtrack
                    }
                return false;
            }
    return true;  // no empty cell left
}

Full walkthrough

Step 1: Represent the grid as a fixed 9×9 array

using Grid = std::array<std::array<int, 9>, 9> — 0 means empty. A fixed-size array matches the problem exactly: Sudoku grids never grow, and the compiler knows the bounds. Input arrives as 9 lines of 9 digits, read char by char ('0' to '9' converted with c - '0').

Step 2: Write ok(): the constraint checker

ok(grid, r, c, n) answers 'may I place n at (r, c)?' by three scans: the row, the column, and the 3×3 box whose top-left corner is (r - r % 3, c - c % 3). That box formula is the one piece of Sudoku maths — derive it once, test it, then never think about it again.

bool ok(const Grid& g, int r, int c, int n) {
    for (int i = 0; i < 9; ++i)
        if (g[r][i] == n || g[i][c] == n) return false;
    int br = r - r % 3, bc = c - c % 3;
    for (int i = 0; i < 3; ++i)
        for (int j = 0; j < 3; ++j)
            if (g[br + i][bc + j] == n) return false;
    return true;
}

Step 3: Write solve(): backtracking in five lines of logic

Find the first empty cell; if none exists, the puzzle is solved — return true. Otherwise try digits 1–9: if ok(), place the digit and recurse; if the recursion returns true, propagate it up; if it fails, ERASE the digit (back to 0) and try the next. The erase-and-continue is the 'backtrack' — the algorithm's willingness to undo is its entire intelligence.

Step 4: Understand why recursion depth is safe here

Each recursive call fills one more cell, so depth never exceeds 81 — trivial for the call stack. The search may visit many branches, but a well-formed puzzle resolves in milliseconds; pathological cases are why the checklist's 'counts solutions' variant exists (keep searching after the first solution, count, and stop at 2 to prove uniqueness).

Step 5: Validate the input before solving

A puzzle whose GIVENS already contradict each other (two 5s in one row) makes solve() hunt forever for an impossible completion. Pre-check: every non-zero cell must pass ok() against the rest. Report 'invalid puzzle' instead of hanging — distinguishing 'unsolvable' from 'invalid' is the checklist's real demand.

Step 6: Print the solved grid readably

Print rows with a space every 3 columns and a divider line every 3 rows, mirroring the printed-puzzle layout. When a human verifies a Sudoku, they scan boxes — your output format should match how the verification happens.

Step 7: Test with a known puzzle and its known solution

The classic example (530070000 / 600195000 / 098000060 / ...) solves to 534678912 / 672195348 / 198342567 / 859761423 / 426853791 / 713924856 / 961537284 / 287419635 / 345286179. Diff your output against it exactly. Then feed an impossible puzzle (a full valid grid with one digit changed) and confirm the program says so instead of spinning.

Common mistakes

Compile and run

g++ -std=c++17 -o sudoku sudoku.cpp

Sample run

$ ./sudoku
Enter the puzzle, 9 lines of 9 digits (0 = empty):
> 530070000
> 600195000
> 098000060
> 800060003
> 400803001
> 700020006
> 060000280
> 000419005
> 000080079
Solving...
5 3 4 | 6 7 8 | 9 1 2
6 7 2 | 1 9 5 | 3 4 8
1 9 8 | 3 4 2 | 5 6 7
8 5 9 | 7 6 1 | 4 2 3
4 2 6 | 8 5 3 | 7 9 1
7 1 3 | 9 2 4 | 8 5 6
9 6 1 | 5 3 7 | 2 8 4
2 8 7 | 4 1 9 | 6 3 5
3 4 5 | 2 8 6 | 1 7 9
Solved. This puzzle has exactly 1 solution.

Try it in your browser

No browser demo is included for this project. Build the C++ version below — that is the real program.

Related Intermediate projects

← All 60 projects · Classic site (Learn & Sandbox)

Download Fake GPS