A high-performance C++ solver for color flood / tile conquest puzzles. The algorithm analyzes a colored grid, compresses connected regions into a graph, and searches for an optimal or near-optimal sequence of color changes required to capture the entire board.
The implementation combines:
- Connected-component extraction
- Union-Find (Disjoint Set Union) region merging
- Compact bitset-based state representation
- Graph-based board abstraction
- Beam-search style exploration
- Duplicate-state elimination through hashing
The result is a solver capable of evaluating thousands of candidate board states while keeping memory usage extremely low.
Instead of operating directly on board cells, the solver first converts the board into a graph of contiguous color regions.
Each region becomes a graph node:
- Nodes represent connected areas of the same color.
- Edges connect adjacent regions of different colors.
- The top-left region becomes the starting territory.
The solver repeatedly selects new colors and expands the currently owned territory until all regions have been absorbed.
The board is scanned and neighboring cells of identical color are merged using a Union-Find structure with path compression.
This produces:
- Unique region identifiers
- Region colors
- Region adjacency information
The total number of regions is limited to:
32 * 6 = 192which allows an extremely compact bitset representation.
Each connected region becomes an Item:
struct Item
{
int color;
int id;
IdSet neighbours[6];
};For every neighboring region pair:
regionA.Link(regionB);the solver records adjacency grouped by target color.
This allows instant lookup of all neighboring regions reachable through a specific color choice.
The IdSet class stores region membership using six 32-bit integers:
int m_data[6];Capabilities include:
- O(1) insertion
- Fast union operations
- Fast difference operations
- Efficient iteration over set bits
- Population counting
- Hash generation
A state containing up to 192 regions occupies only 24 bytes of raw bit storage.
Each candidate solution is represented by a Course:
struct Course
{
IdSet items;
IdSet covered[6];
Moves moves;
};Where:
items= currently captured regionscovered[color]= cached regions already processed for a colormoves= sequence of color selections
The solver does not perform exhaustive search.
Instead it maintains only the strongest candidate states:
vector<Course*> courses;For every move:
- Generate successors for all colors.
- Expand territory.
- Remove duplicate states.
- Keep only the best
numCoursescandidates.
This acts as a beam search where board coverage is the primary heuristic.
A custom hash table prevents revisiting identical region sets:
unsigned int hash()
{
return m_data[0] ^
m_data[1] ^
m_data[2] ^
m_data[3] ^
m_data[4] ^
m_data[5];
}States are compared using exact bitset equality.
This significantly reduces branching and search cost.
The solver uses a custom Bit Scan Forward implementation:
unsigned int BSF(unsigned int v)allowing iteration over active regions without scanning all possible IDs.
Set cardinality is computed using a SWAR-style bit counting algorithm:
v = v - ((v >> 1) & 0x55555555);
v = (v & 0x33333333) +
((v >> 2) & 0x33333333);avoiding per-bit loops.
Candidate states are allocated from a fixed-size pool:
Course* pCoursePool =
new Course[numCourses * 2];This minimizes:
- Dynamic allocations
- Heap fragmentation
- Allocation overhead
during search.
Region extraction:
O(N² α(N))
where:
N × N= board sizeα= inverse Ackermann function from Union-Find
Effectively close to linear.
Depends on:
- Number of regions
- Beam width (
numCourses) - Maximum move depth
Approximate upper bound:
O(depth × beamWidth × colors)
with:
colors = 6
making the search practical even for large boards.
| Structure | Purpose |
|---|---|
IdSet |
Compact bitset representation of region IDs |
Item |
Graph node representing a connected region |
Moves |
Fixed-size move sequence storage |
Course |
Search state |
| Union-Find arrays | Region extraction and merging |
| Hash table | Duplicate-state detection |
- Connected-component compression
- Graph-based board abstraction
- Union-Find region merging
- Compact 192-bit state representation
- Beam-search optimization
- Duplicate-state elimination
- Memory-pool allocation
- Fast bit-level iteration
- Low memory footprint
- Suitable for Flood-It / Color Flood style games
vector<int> DoSolve(Board& originalBoard,
int numCourses);Returns a sequence of color indices representing the moves required to flood the entire board.
Example:
[3, 1, 5, 2, 4, 0]Each number corresponds to a board color selected at that step.
This solver transforms a color-flood puzzle into a graph search problem. By combining region compression, bitset-based state encoding, hashing, and beam search, it efficiently explores large solution spaces while maintaining very low memory consumption. The implementation is heavily optimized toward speed and is designed to solve Flood-It style puzzles in a fraction of the time required by naive cell-based approaches.
