DEV Community

Cover image for Remember That Dot Game We Played on Paper? I Made It Digital So We Never Forget It
Muhammad Usman
Muhammad Usman

Posted on • Originally published at Medium

Remember That Dot Game We Played on Paper? I Made It Digital So We Never Forget It

The game is called Box & Dots

This is the game we all used to play in our childhood. Those were good old days. It happened some days ago when I was sitting at home with my wife, my life partner, playing this game on paper with a pen. There were many games we used to enjoy back in the day that children nowadays don’t even know. So I thought, why not digitalize it? That’s where the journey started.

There is something about this game that never gets old. Two people, a pen, and a grid of dots, and suddenly the next thirty minutes are gone. No app, no screen, and no battery required. Just focus on strategy and that satisfying moment when you complete a box and write your initial inside it before your opponent can say anything.

I built this for all of us. It is free. Go play it and tell me if it brought back any memories.

Dots & Boxes | The Game of Lines, Boxes & Bragging Rights

The classic pencil-and-paper strategy game, now online. Play with a friend or challenge the Computer. Free & instant.

favicon box-and-dots.netlify.app

Somewhere in the middle of that game with my wife, it hit me. There are so many people who used to play this who would love to play it again, but the people they want to play with are not in the same room anymore. Some are in different cities. Some are in different countries. And yet this game deserves to be played properly, not forgotten in the back pages of old notebooks.

So I built it.

What the game is, if you somehow forgot

You start with a grid of dots. Players take turns drawing one line at a time, connecting two dots either horizontally or vertically. The goal is to complete the fourth side of a box. The moment you do, that box is yours and you get an extra turn, just like the original rules we all played by. Once every box is claimed, whoever has the most wins. Simple as it always was.

How I built it

The entire game is a single HTML file. No frameworks, no libraries, no backend server. Just HTML, CSS, and vanilla JavaScript. I wanted it to be something anyone could open in a browser and play instantly, with no installation, no account, and nothing standing between you and the game.

Everything that is in it

Play with a friend on the same device

The game tracks turns automatically. After every move it checks whether a box was completed. If yes, the same player goes again. If not, it switches to the other player.

const gained = checkBoxes(currentPlayer);
if (!gained) currentPlayer = 1 - currentPlayer;
Enter fullscreen mode Exit fullscreen mode

Simple as that. One line does the turn switching.

Drawing the board with Canvas

The board is drawn on an HTML Canvas element. Every dot, line, and filled box is rendered using the Canvas 2D API. When you hover over a gap between two dots, it previews your line in your color. When a box is completed, it fills softly, and your emoji appears inside it.

// Draw a placed line with a glow effect
cx.strokeStyle = COLORS[playerIndex];
cx.lineWidth = 3.5;
cx.shadowColor = COLORS[playerIndex];
cx.shadowBlur = 14;
cx.beginPath();
cx.moveTo(a.x, a.y);
cx.lineTo(b.x, b.y);
cx.stroke();
Enter fullscreen mode Exit fullscreen mode
// Draw emoji inside a claimed box
cx.font = `${CELL * 0.28}px serif`;
cx.textAlign = 'center';
cx.textBaseline = 'middle';
cx.fillText(playerAvatar, x + CELL/2, y + CELL/2);
Enter fullscreen mode Exit fullscreen mode

Checking if a box is complete

Every time a line is placed, the game checks all four sides of every neighboring box. If all four sides are drawn, the box is claimed.

function checkBoxes(player) {
  let gained = 0;
  for (let r = 0; r < G-1; r++) {
    for (let c = 0; c < G-1; c++) {
      if (!boxes[r][c] &&
           hL[r][c] && hL[r+1][c] &&
           vL[r][c] && vL[r][c+1]) {
        boxes[r][c] = player + 1;
        gained++;
      }
    }
  }
  return gained;
}
Enter fullscreen mode Exit fullscreen mode

hL holds horizontal lines, vL holds vertical lines. Each cell in the grid just needs all four sides filled.

Undo

Before every move the full game state is pushed onto a stack. Hitting undo pops the last snapshot and restores everything exactly as it was.

// Save state before placing a line
undoStack.push({
  hL:    hL.map(r => [...r]),
  vL:    vL.map(r => [...r]),
  boxes: boxes.map(r => [...r]),
  cur,
  scores: [...scores]
});
Enter fullscreen mode Exit fullscreen mode
// Restore on undo
const s = undoStack.pop();
hL = s.hL; vL = s.vL;
boxes = s.boxes;
cur = s.cur;
scores = [...s.scores];
Enter fullscreen mode Exit fullscreen mode

Sound with Web Audio API

No audio files, no external assets. Every sound is generated programmatically using oscillators. A short tone when a line is drawn, a small rising melody when a box is claimed.

function beep(freq, type, duration, volume = 0.18) {
  const ac = new AudioContext();
  const oscillator = ac.createOscillator();
  const gain = ac.createGain();
  oscillator.connect(gain);
  gain.connect(ac.destination);
  oscillator.type = type;
  oscillator.frequency.setValueAtTime(freq, ac.currentTime);
  gain.gain.linearRampToValueAtTime(volume, ac.currentTime + 0.01);
  gain.gain.exponentialRampToValueAtTime(0.001, ac.currentTime + duration);
  oscillator.start();
  oscillator.stop(ac.currentTime + duration);
}
Enter fullscreen mode Exit fullscreen mode
// Line placed
beep(360, 'sine', 0.07);// Box claimed — three rising tones
beep(520, 'triangle', 0.08, 0.18);
beep(660, 'sine',     0.10, 0.18);
beep(780, 'sine',     0.12, 0.18);
Enter fullscreen mode Exit fullscreen mode

Play online with a friend anywhere in the world

This was the most interesting part to build. I used PeerJS, which sits on top of WebRTC, to create a direct peer-to-peer connection between two browsers. No server in the middle. No data leaving your device except the move itself.

When you create a room, a unique ID is generated and embedded into a shareable link. Your friend opens that link, both browsers handshake, and from that point every move is sent directly between devices.

// Host creates a room
const peer = new Peer(roomId);
peer.on('connection', conn => {
  // Send initial game config to guest
  conn.send({ type: 'init', cfg, mySlot: 1 });
});
Enter fullscreen mode Exit fullscreen mode
// Guest joins
const conn = peer.connect(roomId);
conn.on('data', data => {
  if (data.type === 'init') startOnlineGame(data.cfg);
  if (data.type === 'move') applyRemoteMove(data.line);
});// Sending a move
conn.send({ type: 'move', line: { t: 'h', r: 2, c: 1 } });
Enter fullscreen mode Exit fullscreen mode

The connection stays alive through restarts and the results screen. If you click Leave it asks for confirmation first so your friend does not get disconnected by accident.

Computer opponent

Three difficulty levels. Easy picks randomly. Medium takes any completing move and avoids gifting boxes. Hard does both and favors the center of the board for maximum control.


function aiMove() {
  const moves = allMoves();
Enter fullscreen mode Exit fullscreen mode
  // Always take a completing move if available
  const winning = moves.filter(completesBox);
  if (winning.length) return winning[0];  // Avoid giving opponent an easy box
  const safe = moves.filter(m => !givesBox(m));
  const pool = safe.length ? safe : moves;  // Hard: prefer centre of board
  if (difficulty === 'hard') {
    const mid = (G - 1) / 2;
    pool.sort((a, b) =>
      Math.hypot(a.r - mid, a.c - mid) -
      Math.hypot(b.r - mid, b.c - mid)
    );
    return pool[0];
  }  return pool[Math.floor(Math.random() * pool.length)];
}
Enter fullscreen mode Exit fullscreen mode

Results and sharing

When the game ends, a result card is generated with both player names, scores, board size, and total moves. One tap copies it, shares it to WhatsApp, or posts it to Twitter.

const result =
`🎮 Dots & Boxes Result
─────────────────
${p0.av} ${p0.name}: ${s0} boxes
${p1.av} ${p1.name}: ${s1} boxes
─────────────────
${winner} · ${G}×${G} grid · ${totalMoves} moves`;
Enter fullscreen mode Exit fullscreen mode
// Share to WhatsApp
window.open('https://wa.me/?text=' + encodeURIComponent(result));
Enter fullscreen mode Exit fullscreen mode

It is the same game. Same rules, same tension, same joy when you trap your opponent into giving you three boxes in a row. My wife still beat me, by the way. Some things never change.

I built this for all of us. It is free. Go play it and tell me if it brought back any memories.

Go send it to someone you used to pass a notebook with. See if they still have it in them.

Dots & Boxes | The Game of Lines, Boxes & Bragging Rights

The classic pencil-and-paper strategy game, now online. Play with a friend or challenge the Computer. Free & instant.

favicon box-and-dots.netlify.app

Top comments (0)