Rummikub — Unity

A complete, playable Rummikub board game built in Unity 6 — drag-and-drop tiles, full rule enforcement, undo support, and a rule-based computer opponent. No minimax, no brute force — every placement resolves in O(1).

Rummikub gameplay screenshot — tiles arranged in runs and groups on the board with the player rack below

Features

Everything the real game does — with the data structures doing the heavy lifting.

🎮

Full Rummikub rules

Runs, groups, jokers, the 30-point initial meld, and win detection — every set on the board is validated before a turn is confirmed.

🖱️

Drag & drop play

Grab tiles from your rack and drop them anywhere legal on the 8×29 board. Extend, merge, and rearrange sets freely once your meld is down.

↩️

Undo system

Every move in a turn is tracked on a stack — one click rolls the board back to the last confirmed state.

🤖

Computer opponent

A layered, deterministic AI that plays full sets, steals spare tiles from board sets, appends loose tiles, and performs multi-step chain extractions — including freeing jokers.

🃏

Smart board maintenance

Sets automatically merge when you bridge them and split when you pull a tile from the middle — data structures updated in place.

O(1) placement engine

No board rescans. Two hash tables and a doubly linked list resolve every edge-connection scenario in constant time.

How to Play

Each player starts with 14 tiles. First meld must total 30+ points from your own rack. First to empty their rack wins.

ActionHow
Place a tileDrag it from your rack onto an empty board slot
Extend / merge setsDrop a tile directly next to an existing set
Rearrange the boardDrag tiles between board slots (once your initial meld is down)
Confirm your turnConfirm — validates every set on the board first
Take back your movesUNDO — restores the board to the start of your turn
Skip / drawClick the Deck — draws a tile and passes the turn

Architecture — the O(1) placement engine

Instead of searching the board for the set a tile belongs to, the game models the board with two hash tables and a custom doubly linked list. Only the two edge tiles of every set are keyed.

cardToSetPos : Dictionary<int, SetPosition>      // key = row * 100 + column  →  set id
validSets    : Dictionary<SetPosition, CardsSet> // set id  →  the actual set
CardsSet     : DoublyLinkedList<Card>            // O(1) add/remove at both ends, O(1) append

When a tile is dropped at (row, col), the engine hashes its two horizontal neighbors (key ± 1) and lands in exactly one of four O(1) scenarios:

ScenarioNeighbor keys foundWork done
New setnoneCreate set, key the tile
Extend left edgeright onlyPrepend to linked list, move the edge key
Extend right edgeleft onlyAppend to linked list, move the edge key
Merge two setsbothAppend one linked list to the other — O(1) — re-key edges

Pulling a tile back off is the mirror image: edge tiles detach in O(1), while pulling from the middle splits the linked list into two sets — O(k) for the k tiles that change set identity, the theoretical minimum.

A run of tiles being split by removing a middle tile