Tic-tac-toe feels trivial — until you try to write an opponent that never loses. The trick is an algorithm called minimax, and it's the same idea underneath the engines that beat chess grandmasters.
Games are trees
Any turn-based game is a tree. The current board is the root, each legal move is a branch to a new board, and those branch again for the opponent's replies. A full game is one path from the root down to a leaf where someone has won or the board is full. Tic-tac-toe's tree is tiny — at most nine moves deep — so a computer can walk the entire thing instantly. That completeness is why perfect play is possible.
Scoring the endings
We only truly know the value of finished games. Score them from the AI's point of view: a win for the AI is +10, a win for you is −10, a draw is 0. Every other position's value is figured out by assuming perfect play from there.
Minimax: assume both sides are perfect
The two players want opposite things. On the AI's turn it takes the maximum child score; on your turn it assumes you'll take the minimum (best for you). Recurse to the leaves and bubble those choices back up:
function minimax(board, isAI) {
const w = winner(board);
if (w) return w === AI ? 10 : w === HUMAN ? -10 : 0;
const scores = empties(board).map(i => {
board[i] = isAI ? AI : HUMAN;
const s = minimax(board, !isAI);
board[i] = "";
return s;
});
return isAI ? Math.max(...scores) : Math.min(...scores);
}
Win sooner, lose later
Plain minimax treats all wins as equal, so the AI might toy with you or walk into an instant loss. Fold the search depth into the score — subtract it from a win, add it to a loss — and it prefers fast wins and stalls losses:
if (w === AI) return 10 - depth;
if (w === HUMAN) return -10 + depth;
Why it's unbeatable
Tic-tac-toe is a solved game: perfect play by both sides always ends in a draw. Minimax plays perfectly, so it takes any win you hand it and steers everything else to at worst a tie. The best you can ever get is a draw.
For bigger games like chess you can't search to the end — you add alpha-beta pruning to skip hopeless branches and a heuristic to estimate positions at a depth limit. But the min/max skeleton is identical.
Play the unbeatable version (and an "easy" random mode) here, with the full walkthrough:
https://dev48v.infy.uk/game/day22-tic-tac-toe.html
Top comments (0)