A high-performance C++ Minesweeper constraint solver that enumerates all valid mine configurations for a partially revealed board.
This project demonstrates advanced constraint propagation, set intersection analysis, combinatorial search, and custom memory allocation techniques to efficiently solve Minesweeper puzzles.
MineSweeperRedux accepts a partially solved 10×10 Minesweeper board and computes every possible mine placement consistent with the revealed numeric clues.
Unlike simple Minesweeper assistants that identify only immediately safe moves, this solver performs a complete logical and combinatorial analysis of the puzzle state, generating all valid solutions.
The project was originally developed as an experiment in:
- Constraint satisfaction problems (CSP)
- Efficient set representation
- Search-space reduction
- Custom STL allocators
- Memory pool optimization
- Bitwise algorithms
Each revealed Minesweeper number is converted into a constraint:
Among these neighboring unrevealed cells, exactly N mines exist.
The solver builds a system of overlapping constraints and repeatedly refines them until all possibilities are resolved.
The engine immediately detects:
- Guaranteed mines
- Guaranteed safe cells
- Contradictory states
- Fully resolved groups
Examples:
{A,B,C} = 0
means all cells are safe.
{A,B,C} = 3
means all cells are mines.
These deductions are propagated through all remaining constraints.
A major optimization is the analysis of overlapping constraint groups.
Example:
{A,B,C,D} = 2
{C,D,E,F} = 2
The solver computes:
Intersection: {C,D}
Left: {A,B}
Right: {E,F}
and derives tighter bounds for each subset.
This frequently eliminates large portions of the search tree before any brute-force enumeration begins.
When pure deduction is no longer sufficient, the solver recursively explores all remaining valid combinations.
Every generated solution satisfies all board constraints.
Output consists of all valid mine layouts.
CellSet is a compact bitset-like container optimized for Minesweeper neighborhoods.
Characteristics:
- Stores up to 32 cells
- Uses a single 32-bit integer
- Constant-time insertion/removal
- Fast iteration using bit scanning
- Extremely low memory overhead
Example:
CellSet neighbors;
neighbors.insert(cell);The project includes a custom implementation of:
unsigned int FastBSF(unsigned int v);which performs a fast "Bit Scan Forward" operation.
Used for:
- Iteration over active bits
- Compact set traversal
- Efficient cell extraction
This avoids heavier generic containers during intensive search operations.
A Group represents a Minesweeper constraint.
struct Group
{
CellSet neighbors;
int countMin;
int countMax;
};Meaning:
countMin ≤ mines(neighbors) ≤ countMax
Initially:
countMin == countMax
but intersection processing may relax or tighten these bounds.
The core solving engine.
Responsibilities:
- Constraint reduction
- Propagation of known mines/safe cells
- Constraint intersection analysis
- Recursive search
- Solution generation
Main entry point:
Prestidigitator::ProduceResults(...)which produces all valid mine configurations.
The solver uses a custom STL allocator:
cached_allocator<T>designed to accelerate frequent allocation of small objects stored inside STL containers.
Benefits:
- Reduced heap fragmentation
- Lower allocation overhead
- Improved search performance
A lightweight object pool used by the allocator.
Features:
- Block allocation
- Free-list recycling
- Constant-time allocation/deallocation
This is especially useful because constraint generation creates many temporary objects.
Inspired by MFC's CPlex.
Provides:
- Chunked memory allocation
- Linked allocation blocks
- Fast bulk cleanup
Instead of individually freeing thousands of small objects, entire memory chains can be released at once.
The solver expects a file named:
input.txt
located next to the executable.
Example:
1.........
2.........
..........
..........
..........
..........
..........
..........
..........
..........
| Character | Meaning |
|---|---|
| 0-8 | Revealed clue |
| Any other character | Unknown cell |
Unknown cells are treated as potential mine locations.
For every valid solution:
1MM......
2M.......
.........
...
where:
M
marks a mine.
After enumeration, timing statistics are displayed:
Time to solve (once): 0.0476 seconds
- Parse board.
- Generate constraints from revealed numbers.
- Apply deterministic reductions.
- Analyze overlapping constraints.
- Repeat until no new information appears.
- Recursively enumerate remaining possibilities.
- Output every valid solution.
Worst-case complexity remains exponential, as Minesweeper solving is closely related to NP-complete constraint satisfaction problems.
However, several optimizations dramatically reduce practical runtime:
- Compact bitset representation
- Constraint propagation
- Group intersection deduction
- Search-space pruning
- Custom allocator
- Memory pooling
For realistic boards, the solver is significantly faster than naïve brute-force enumeration.
Any modern C++ compiler supporting STL containers should build the project.
Example:
g++ MineSweeperRedux.cpp -O3 -std=c++11 -o MineSweeperReduxor using Visual Studio:
cl /O2 MineSweeperRedux.cppThis project is an interesting example of:
- Constraint satisfaction systems
- Logical inference engines
- Bit manipulation techniques
- Search optimization
- Custom allocators
- Memory pooling
- Efficient STL integration
It demonstrates how a seemingly simple puzzle can be transformed into a sophisticated constraint-solving problem.
