- Greedy Algorithms: Used by the CPU to pick the immediate best move based on local heuristics.
- Dynamic Programming (DP): Used in the
solve_dpsolver to store and reuse subproblem solutions via memoized recursion over a frontier state. - Backtracking (BT): Used in
solve_btandsolve_dacto systematically explore the state space of tile rotations. - Divide and Conquer (D&C):
- Merge Sort: Implemented in
SortUtils.hppto sort tiles by their constraint priority. - DAC Solver: Implemented in
DacSolver.hppto recursively split the board into regions and solve them based on boundary compatibility.
- Merge Sort: Implemented in
- Graph Traversal (DFS): Used for connectivity checks, component counting, and cycle detection.
The DP solver operates in
Merge Sort is a stable, Divide and Conquer algorithm that guarantees
The CPU evaluates all possible rotations for every unlocked tile (
The game is modeled as a Graph where each tile is a node and each connection is an edge. We use an optimized Adjacency List using a flattened std::vector<std::vector<pair<int, int>>> where nodes are indexed by their position in the 1D grid. This allows for
-
1D Grid Flattening: Switched from a 2D
vector<vector<Tile>>to a 1Dvector<Tile>to improve cache locality and reduce memory fragmentation. -
Bitwise Port Operations: Replaced port-list comparisons with
uint8_tbitmasks and bitwise logic (&,|,<<). This allows constraint checking to happen in constant time without memory allocations. -
Graph Flattening: Replaced
std::map-based adjacency lists with integer-indexedstd::vector, removing the$O(\log V)$ overhead from map lookups. -
Visited State Maps: Replaced
std::setwithstd::vector<bool>for DFS and connectivity checks, ensuring$O(1)$ lookup and insertion.
For wrapping boards, the solvers (DP especially) must account for the connection between the last row/column and the first row/column. The DP solver brute-forces the initial boundary constraints and ensures they match at the end of the recursion.
We use DFS from the power source to ensure:
- All PCs are reachable (connectivity).
- The number of visited nodes equals the total non-empty nodes.
- No back-edges are found during DFS (acyclicity).
- No "loose ends" exist (all ports have a matching neighbor).
- JavaFX provides a modern, responsive UI.
- C++ offers high performance for computationally intensive tasks like recursive state-space exploration (BT, DP, DAC) and graph analysis.
- JSON/IPC serves as a clean interface between the two components.