C++ Sudoku Solver Project
Feed it any Sudoku puzzle; backtracking finds the solution in milliseconds.
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
- Recursive backtracking
- Constraint checking (row, column, box)
- Searching for the next empty cell
- Why trying candidates in order matters for speed
Feature checklist
- Enter a puzzle as 9 lines (0 = empty)
- Solves any valid puzzle
- Prints the solved grid neatly
- Detects unsolvable/invalid puzzles
- Counts solutions (is the puzzle unique?)
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
- Forgetting to reset the cell to 0 when a branch fails — the grid keeps the wrong digit and every later branch is poisoned.
- Computing the box corner as (r / 3, c / 3) without multiplying back by 3, checking a box in the top-left region for every cell.
- Solving a puzzle with contradictory givens and concluding the solver is slow, when it is actually searching a space with no solution.
Compile and run
g++ -std=c++17 -o sudoku sudoku.cppSample 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.