DO← Back to Work
01 / Case StudySoftware / AI / Realtime

Connect
Four.

A realtime multiplayer strategy game that grew from a local React experiment into a room-based Socket.IO system with public matchmaking, spectators, synchronized rematches, and adversarial AI.

Impossible AIMinimax / Alpha-Beta

A Board Game That Kept Becoming a Systems Problem.

Connect Four started as a straightforward local game. Each new capability changed what the system needed to handle: stronger AI introduced search complexity, online play introduced shared state, and spectator mode exposed the challenges of synchronizing clients that could join at different points in a game.

Role
Full-Stack Developer
Client
React
Server
Node.js / Socket.IO
Focus
Realtime State / AI

Every Feature Changed The Architecture.

01Local Play

Board state, turn handling, and win detection.

02Adversarial AI

Difficulty levels, minimax, evaluation heuristics, and alpha-beta pruning.

03Multiplayer

Socket.IO rooms, player assignment, and realtime move propagation.

04Public Rooms

Discoverable games alongside private room codes.

05Spectators

Read-only participants sharing the same live game.

06State Sync

Current-state snapshots for clients joining an existing game.

One Room.
Multiple Clients.
Shared State.

Online games are organized around a shared room. React clients communicate through Socket.IO while the Node server coordinates room membership, players, spectators, board snapshots, and the current turn.

01React Client
Host

Creates the room and participates as one of two active players.

Player
02React Client
Guest

Joins a public or private room and receives live game updates.

Player
03React Client
Spectator

Receives shared game state without occupying a player slot.

Read Only
Socket.IORealtime Event Transport
↓ Move / Join / Rematch↑ Room Events / State Sync
Node.js ServerRoom State
● Live
ROOMABC123Shared Context
PlayersHost / Guest
Spectators0 — N
Board6 × 7 Snapshot
TurnCurrent Player
CLIENT

Renders the board, handles interaction, and emits player actions.

TRANSPORT

Socket.IO moves events between connected clients and the shared room.

SERVER

Maintains room-level shared state and coordinates connected participants.

Architecture Note

The server coordinates shared room state rather than acting as a fully authoritative game engine. Clients still participate in game logic and local state management. An architectural tradeoff I revisit later in the case study.

What Happens When
A Client Joins Halfway
Through?

Spectator mode exposed a flaw in the original realtime model. Clients already inside a room could stay synchronized through live move events, but a spectator joining mid-game had missed every event that came before.

The Problem

Live Events Only Describe What Changed.

If a spectator joined from the beginning, each move arrived normally and their board stayed in sync. If they joined later, their client started from an empty board because it had no history of the moves that already happened.

Existing PlayersLive
Current game state
Late Join→
New SpectatorMissing History
Local board starts empty
The Realization
Events Tell You What Happened.State Tells You What Is True Now.
The Fix

Hydrate First.
Stream Updates Second.

The server began keeping a current board snapshot and active-player value for each room. A late spectator could first receive that snapshot, then continue listening for normal realtime events.

01Spectator JoinsjoinAsSpectator
↓
02Server Reads Room Stateboard + currentPlayer
↓
03Snapshot SentsyncBoard
↓
04Client Hydratesboard / turn
↓
05Live Events ContinueopponentMove
Engineering Takeaway

The bug changed how I thought about realtime systems. A stream of updates can keep existing clients synchronized, but new clients still need a trustworthy representation of current state. That distinction became important once the application had participants entering the same session at different times.

Searching For A Move
Before Making One.

The computer opponent evolved through four difficulty levels. Each one uses a different decision strategy, from simple randomness to recursive game-tree search with pruning and board evaluation.

01Easy
Random

Choose Any
Valid Move.

The simplest opponent selects randomly from the columns that can still accept a piece.

02Medium
Heuristic

React To Immediate
Threats.

Medium difficulty looks for tactical opportunities such as winning moves, blocking the opponent, and preferring stronger board positions.

03Hard
Search

Look Several Turns
Ahead.

Hard difficulty uses depth-limited minimax, recursively exploring possible responses before selecting the strongest evaluated move.

The Core Idea

Don't Ask What Move Looks Best Now.

Ask what happens after the opponent responds, then after the AI responds again. Minimax recursively evaluates those future states while assuming both players continue choosing their strongest available moves.

MAXAI
C3+5
C4+8Best
C5+5
Representative evaluationHigher score favors AI
Next / Search Implementation

The challenge was not implementing recursion. It was making the search useful without exploring every possible future board state.

Making Search Useful
Without Exploring
Everything.

Recursive search becomes expensive quickly. The strongest AI combines bounded search, move ordering, heuristic board evaluation, and alpha-beta pruning so it can spend more computation on branches that are actually capable of changing the decision.

01 / Branching Factor

One Extra Search Level Multiplies The Work.

At any position, the AI can have as many as seven legal columns to consider. Each of those moves creates another set of possible opponent responses, and the tree expands recursively.

Depth0123456
Current Board1
Possible Moves7
Possible Responses49
Depth 3343
Depth 42,401
Depth 516,807
Depth 6117,649
Upper-bound illustration

Real searches are smaller because columns fill, games terminate, and alpha-beta pruning removes branches early.

02 / Move Ordering

Search Stronger Candidates First.

The AI prioritizes columns near the center of the board. Center positions participate in more possible Connect Four lines, and evaluating promising moves earlier can tighten alpha-beta bounds sooner.

Candidate Search OrderCenter → Edge
01C4
02C3
03C5
04C2
05C6
06C1
07C7
C106
C204
C302
C401
C503
C605
C707
03 / Board Evaluation

A Future Board Needs a Numerical Value.

Minimax cannot always search until the game is finished. At the depth limit, a heuristic estimates whether the position favors the AI or the opponent.

Center Control+3

Reward pieces placed in the center column.

Four AI Pieces+100

Strongly reward completed winning windows.

Three + Empty+10

Reward positions one move away from four.

Two + Two Empty+5

Preserve developing offensive opportunities.

Opponent Three + Empty-8

Penalize positions containing an immediate threat.

Evaluation Windows
Horizontal ↔Vertical ↕Diagonal ↗Diagonal ↘
04 / Alpha-Beta Pruning

Stop Searching Branches That Cannot Change The Answer.

Minimax still produces the same decision, but alpha-beta pruning avoids evaluating parts of the tree once the current bounds prove that a branch cannot outperform an already-known move.

MAXAI
C3+5
MIN+5
C4+8α = +8
MIN+8
C5≤ +4
β ≤ αPruned
Same final decisionLess unnecessary search
05 / Search Depth

Better Decisions Cost More Computation.

Search depth is bounded rather than allowed to expand indefinitely. The implementation adjusts its depth based on the remaining board state, balancing how far ahead the AI looks against the amount of work required for each move.

Empty Cells> 30Depth 6
Empty Cells16 — 30Depth 5
Empty Cells≤ 15Depth 4
Engineering Principle

The expensive part is not scanning a 6 × 7 board. It is placing that work inside a recursively expanding tree. This project made the difference between code that is merely correct and code whose computational cost still makes sense as the amount of work grows.

The Hardest Problems
Appeared After The
Code Already Worked.

Connect Four started as a small personal project. As multiplayer, spectators, stronger AI, public rooms, and rematches were added, decisions that seemed minor early on began affecting the rest of the system.

01State Ownership

Shared Systems Need A Source Of Truth.

Realtime events were enough while every client entered the game at the same point. Spectators joining later exposed the weakness of relying only on local state and incremental updates.

LessonDefine who owns current state.
02Complexity

Correct Code Can Still Become Expensive Code.

A board evaluation is inexpensive by itself. Repeating that work across a recursively expanding game tree completely changes the computational cost.

LessonUnderstand where work multiplies.
03Architecture

Features Change The Shape of The System.

Local play needed board state and turn logic. Multiplayer introduced rooms and event transport. Spectators required shared state. Stronger AI introduced search and performance constraints.

LessonDesign for change, not just today.
Architectural Tradeoff

Coordinated By The Server.
Not Fully Owned By It.

The server maintains room-level shared state and coordinates connected participants, but clients still participate in portions of the game logic and local state management.

That architecture was enough for the project, but it also showed me the difference between adding coordination to an existing client-driven system and designing an authoritative server model from the beginning.

Current ApproachServer-Coordinated
  • 01Clients retain local game logic
  • 02Socket.IO distributes realtime events
  • 03Server stores shared room snapshots
  • 04Lower restructuring cost
vs
If Rebuilt TodayServer-Authoritative
  • 01Server validates every move
  • 02Server owns canonical game state
  • 03Clients render synchronized snapshots
  • 04Clearer ownership as features grow
Beyond the Project

The Game Was Small.
The Engineering Lessons Weren't.

The same questions show up in larger software systems: where state should live, how clients stay consistent, how computational work scales, what happens when requirements expand, and when an existing architecture needs to evolve instead of accumulating another workaround.

01Make ownership explicit.

Shared data becomes easier to reason about when there is a clear source of truth.

02Measure repeated work.

Small operations become expensive when they sit inside loops, recursion, or high-frequency paths.

03Expect requirements to grow.

The best architecture is not the one with the most abstractions. It is the one that can absorb the next reasonable change.

04Revisit earlier decisions.

A decision that made sense for version one may become the constraint in version four.

Play it.
Read The Code.
See The System.

Connect Four became an exercise in realtime state, algorithmic search, synchronization, and evolving architecture. All from a game that started with a single board and two players.