Skip to content
← 1001 Widgets
N° 044 · ●●○

Connect Four

Seven columns, six rows, falling pieces: Connect Four for two players, or against a computer that knows how to block. The right exercise to move from tic-tac-toe to a bigger grid, with gravity added.

JS
What you'll learn
  • Simulate gravity by finding the lowest free cell
  • Detect four aligned pieces in all four directions
  • Write a small AI that wins, blocks and avoids traps
Why this language

Pourquoi un Puissance 4 ? C'est le cousin du morpion, mais on ne choisit plus sa case : on choisit une colonne, et le pion tombe tout en bas. Cette seule règle change tout le code.

Pour savoir si un coup gagne, inutile de parcourir toute la grille. On part de la case jouée et on compte les pions identiques dans les deux sens, sur l'horizontale, la verticale et les deux diagonales. Quatre ou plus, c'est gagné.

L'ordinateur suit trois règles simples : gagner s'il le peut, bloquer si on va gagner, et ne jamais jouer sous une case qui offrirait la victoire. Assez pour donner du fil à retordre.

Pourquoi en JavaScript simple ? Un tableau à deux dimensions, quatre directions et une boucle. Les pions pleins et creux se distinguent sans dépendre des couleurs.

How it works
  1. LA GRILLE

    6 rangées de 7 colonnes. 0 = vide, 1 et 2 = les joueurs.

    const L = 6, C = 7;
    const grille = Array.from({ length: L }, () => Array(C).fill(0));
    let tour = 1;
  2. LA GRAVITÉ

    Le pion prend la case libre la plus basse de la colonne.

    function caseLibre(c) {
      for (let r = L - 1; r >= 0; r--) if (!grille[r][c]) return r;
      return -1;                               // colonne pleine
    }
  3. QUATRE EN LIGNE

    On compte autour de la case jouée, dans les deux sens de chaque direction.

    const DIRECTIONS = [[0, 1], [1, 0], [1, 1], [1, -1]];
    function gagne(r, c) {
      const p = grille[r][c];
      return DIRECTIONS.some(([dr, dc]) => {
        let n = 1;
        for (const s of [-1, 1]) {
          let rr = r + dr * s, cc = c + dc * s;
          while (grille[rr]?.[cc] === p) { n++; rr += dr * s; cc += dc * s; }
        }
        return n >= 4;
      });
    }
  4. JOUER

    function jouer(c) {
      const r = caseLibre(c);
      if (r < 0) return;
      grille[r][c] = tour;
      if (gagne(r, c)) return victoire(tour);
      tour = 3 - tour;                         // 1 devient 2, 2 devient 1
    }
  5. L'ORDINATEUR

    Gagner si possible, sinon bloquer, sinon le centre.

    function choixIA() {
      const libres = [3, 2, 4, 1, 5, 0, 6].filter(c => caseLibre(c) >= 0);
      const essaie = (c, p) => { const r = caseLibre(c); grille[r][c] = p; const ok = gagne(r, c); grille[r][c] = 0; return ok; };
      return libres.find(c => essaie(c, 2)) ?? libres.find(c => essaie(c, 1)) ?? libres[0];
    }
Pitfalls

PIÈGE 1 : Vérifier toute la grille à chaque coup

Pitfall

Mauvais : parcourir les 42 cases et toutes les lignes possibles après chaque pion.

Fix

Correct : seul le dernier pion peut créer un alignement. On part de lui, dans quatre directions.

PIÈGE 2 : Sortir de la grille

Pitfall

Mauvais : lire grille[-1][c] en comptant vers le haut. On obtient une erreur au lieu de undefined.

Fix

Correct : vérifier les bornes, ou utiliser grille[rr]?.[cc] qui renvoie undefined sans planter.

PIÈGE 3 : Une IA qui offre la victoire

Pitfall

Mauvais : jouer au centre sans regarder la case du dessus. L'adversaire pose son pion juste après et gagne.

Fix

Correct : simuler le coup, puis vérifier que la case qui se libère au-dessus ne fait pas gagner l'adversaire.

PERSONNALISER
  • Un minimax limité à quatre ou cinq coups d'avance, comme celui du morpion imbattable.
  • Une variante « Puissance 5 » sur une grille de 9 colonnes.
  • Un historique pour rejouer la partie coup par coup.
OPTIMISATION
  • Pour une IA profonde, représentez chaque joueur par un nombre de 64 bits : les alignements se testent avec quelques décalages binaires.
  • Ne recréez que la colonne jouée plutôt que toute la grille à chaque coup.
VERS REACT

La grille vit dans un useState ; chaque coup crée une copie avec map pour que React voie le changement.

Le coup de l'ordinateur se lance dans un useEffect quand c'est son tour, avec un petit délai nettoyé au démontage.

L'animation de chute se relance en donnant une key unique au dernier pion posé.

Comments
0/1000

Loading comments…

Audience measurement

With your consent, this site measures its traffic with Google Analytics and the Meta pixel, via Google Tag Manager. Nothing is loaded until you choose, and you can change your mind at any time with the "Cookies" link at the bottom of the page.