You Might Also Like
Connect Four vs Computer — Free HTML CSS JS Snippet
Connect Four vs Computer · Cards · Plain HTML, CSS & JS · Live preview
What's included
Features
About this UI Snippet
Connect Four vs Computer — Grid Gravity Drop, 4-Direction Win Detection & Heuristic AI Opponent

Connect Four is a two-player strategy game built on a deceptively simple mechanic: discs fall under gravity into one of seven columns, stacking on top of whatever is already there, and the first player to line up four discs of their own colour horizontally, vertically, or diagonally wins. This snippet implements the full game as a genuine playable board — not a static mockup — complete with real gravity simulation, four-direction win checking, and a heuristic computer opponent that plays a credible game rather than moving randomly.
The gravity model: a 2D array, not pixel maths
The board is represented as a 7-column array of 6-row arrays, board[col][row], where row 0 is the bottom of the column. Instead of placing a disc exactly where the user clicked, lowestEmptyRow(col) scans the column from the bottom upward and returns the first null slot — that index is where the disc actually lands. This is the real mechanic behind Connect Four's gravity: clicking anywhere in a column always drops into the lowest available cell, and the CSS reinforces it visually by laying each column out with flex-direction: column-reverse so cell index 0 renders at the bottom. The falling animation itself is pure CSS — a .c4-disc starts at transform: scale(0) translateY(-140%) and animates to scale(1) translateY(0) with a bouncy cubic-bezier(0.34, 1.56, 0.64, 1) easing curve that gives the drop a satisfying overshoot.
Four-direction win detection
After every move, checkWin(col, row, player) walks outward from the just-placed disc along four axis pairs: horizontal [1, 0], vertical [0, 1], and both diagonals [1, 1] and [1, -1]. For each direction it counts matching discs going forward and then counts again going backward along the same axis, because a winning line can extend on either side of the disc that completed it. If the combined run reaches four or more, the coordinates of that line are returned and each winning cell gets a .win-cell class that adds a glowing green ring and a slow pulsing brightness animation, making the winning line immediately obvious.
The heuristic AI: three priorities, no brute force
The computer opponent does not use minimax or a deep search tree — it applies three ordered heuristics that are exactly how a competent human casual player thinks about the game. First, wouldWin(col, COMPUTER) temporarily drops a yellow disc into every legal column and re-runs checkWin to see whether that move produces an immediate four-in-a-row; if any column does, the computer takes it and wins on the spot. Second, if no winning move exists, the same check runs with HUMAN as the hypothetical player — if the human could win next turn by dropping into some column, the computer occupies that column itself to block it. Third, if neither an immediate win nor a necessary block exists, the computer falls back to positional strategy: it prefers columns in centerOrder = [3, 2, 4, 1, 5, 0, 6], trying the centre column first and working outward. This reflects real Connect Four theory — the centre column participates in more possible four-in-a-row lines (horizontal, vertical, and both diagonals) than any edge column, so occupying it early creates more future winning threats.
Session scoring and disc rendering
A running tally of wins, losses, and draws persists across rounds in a scores object and renders in three coloured score pills above the board. Each disc is a separate absolutely-positioned <div> layered on top of an empty circular cell rather than a background-colour change, which is what makes the drop-in scale animation possible — the disc element itself animates in, rather than a colour simply appearing.
Build with AI
Build, Understand, Optimize, and Extend It With AI
Paste this snippet's full HTML, CSS, and JS into an AI coding assistant like Claude and ask it to trace exactly how lowestEmptyRow() and the column-reverse CSS layout work together to simulate gravity, since that combination is the trickiest part of the whole implementation to reason about from code alone. It's also a great candidate for AI-assisted extension: ask it to add a minimax search with alpha-beta pruning to the computer opponent so it can look several moves ahead instead of only checking immediate wins and blocks, or ask it to implement a local two-player hot-seat mode by removing the setTimeout(computerMove) call. You could also ask the assistant to explain why centerOrder prioritises the middle columns from a game-theory perspective, or to add a move-undo feature that pops the last disc off both the board array and the DOM. Treat this as a working reference to interrogate and build on, not a finished black box.
Prompt to recreate it
Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:
Build a playable Connect Four game in plain HTML, CSS, and JavaScript against a heuristic computer opponent — no frameworks, no build step.
Requirements:
- A 7-column by 6-row grid where clicking a column drops a disc into the lowest currently-empty cell of that column via real gravity simulation (an internal 2D array, not pixel-position placement), animated with a bouncy CSS drop-in transition.
- Win detection that checks all four directions (horizontal, vertical, both diagonals) from the most recently placed disc, correctly counting matches in both directions along each axis so a line completed on either side of the new disc is detected.
- A computer opponent that, on each of its turns, first checks every legal column for an immediate winning move and takes it if one exists; otherwise checks whether the human has an immediate winning move available and blocks it; otherwise chooses the most central available column, since central columns participate in more potential four-in-a-row lines.
- A clear visual highlight (for example a glowing outline) applied specifically to the four discs that form a winning line, distinguishing a win from a normal board state at a glance.
- A running scoreboard tracking wins, losses, and draws across multiple rounds within the same session, updated automatically at the end of each game.
- A "New Game" control that resets the board state and all disc elements without resetting the session scoreboard.
- Prevent any interaction with full columns or with the board after a game has ended, and clearly communicate the game state (whose turn it is, thinking, win, loss, draw) via a status message.Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.
Step by step
How to Use
- 1Drop a discClick anywhere in a column to drop a red disc into the lowest empty cell of that column. The disc animates in with a bouncy fall — you cannot click a specific row, only a column, exactly like the physical game.
- 2Watch the computer respondAfter your move, the status line reads "Computer is thinking..." for a short 450ms delay before computerMove() runs. This pause exists purely for pacing — the AI itself resolves instantly via the three-tier heuristic in wouldWin() and centerOrder.
- 3Read the win highlightWhen four discs connect in any of the four directions, checkWin() returns the exact winning coordinates and each of those four discs gets the .win-cell class, adding a glowing green ring and pulsing brightness so the winning line is unmistakable.
- 4Track the session tallyThe three score pills above the board (You / Draws / Computer) increment automatically via updateScoreboard() at the end of every round and persist in memory across "New Game" clicks within the same page load.
- 5Start a fresh boardClick "New Game" to call createBoard(), which resets the board array to a 7x6 grid of nulls, clears all disc elements, and re-enables column clicks without touching the session score tally.
- 6Customise the AI difficultyTo make the computer weaker, remove the wouldWin(c, HUMAN) blocking check so it only takes immediate wins. To make it stronger, extend wouldWin() to look two moves ahead, or add a check for moves that create a double-threat (two simultaneous three-in-a-rows).
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
No — the AI always follows the same three-tier priority: take an immediate winning move if one exists, otherwise block the human's immediate winning move if one exists, otherwise pick the most central available column. It never makes a deliberately weak or random move, so it plays a consistent, fair, moderately challenging game every round.
checkWin() iterates over four direction vectors: [1,0] for horizontal, [0,1] for vertical, [1,1] for the rising diagonal, and [1,-1] for the falling diagonal. For each vector it counts matching discs both forward and backward from the placed disc along that same axis, so a diagonal line that extends on either side of the new disc is still correctly detected as connected.
Yes. The current wouldWin() helper only simulates one move ahead. To add lookahead, extend it into a minimax function that recursively simulates the human's best response to each computer move and scores the resulting position, then picks the column with the best worst-case outcome. A depth of 4-6 plies is typically enough to make Connect Four very difficult to beat for a casual player.
Column-first indexing matches how the player actually interacts with the game — clicking a column and letting gravity decide the row. lowestEmptyRow(col) can then simply scan board[col] from index 0 upward without needing to transpose coordinates, which keeps both the drop logic and the CSS column-reverse layout consistent with the same mental model.
Not out of the box, but it is a small change: remove the setTimeout(computerMove) call inside handleColumnClick and instead track whose turn it is with a currentPlayer variable that toggles between red and yellow after every successful drop, calling placeDisc and checkWin identically for both players.