🟡 Quatre en ligne néon

Un quatre-en-ligne rétro à l'ambiance néon: le Glouton affronte le Fantôme, jeton par jeton. Déplacez le sélecteur avec les flèches gauche / droite et laissez tomber un jeton avec la flèche du bas. Premier à aligner quatre jetons (horizontale, verticale ou diagonale) gagne la partie.

Quatre en ligne néon

Appuyez sur une flèche du clavier pour commencer.

🟡 Glouton: 0 👻 Fantôme: 0
déplacer le sélecteur laisser tomber le jeton recommencer après une partie

Comment jouer

Les flèches gauche et droite déplacent le sélecteur au-dessus de la grille, avec bouclage d'un bord à l'autre. La flèche du bas laisse tomber un jeton dans la colonne visée. Après une manche, la flèche du haut relance.

Le plateau fait sept colonnes sur six rangées. Le Glouton commence, puis les deux camps alternent à chaque jeton posé. Le premier à aligner quatre jetons, en horizontale, en verticale ou sur l'une des deux diagonales, remporte la manche, et la ligne gagnante s'illumine.

Si la grille se remplit sans alignement, la manche est nulle. Le pointage des deux camps se conserve: relancer vide la grille, pas le décompte.

Comment c'est construit

La grille est un tableau de six rangées de sept cases contenant null, 1 ou 2, la rangée zéro étant celle du haut. Poser un jeton ne demande aucune simulation: lowestEmptyRow remonte la colonne depuis le bas et renvoie la première case libre, et columnFull se contente de regarder la case du haut. La destination est donc connue avant même que l'animation commence.

La détection d'alignement est la partie que je trouve la plus propre. Plutôt que de balayer les quarante-deux cases après chaque coup, checkWinAt part de la seule case qui vient de changer et explore quatre vecteurs: [0,1] pour l'horizontale, [1,0] pour la verticale, puis [1,1] et [1,-1] pour les deux diagonales. Pour chacun, il avance dans le sens positif tant que la case appartient au même joueur, puis recule dans le sens négatif, en accumulant les coordonnées au passage. Si la liste atteint quatre entrées, elle est retournée telle quelle et sert directement à tracer le trait lumineux. Un seul parcours donne à la fois le verdict et la géométrie.

La chute est une vraie petite intégration numérique. Le jeton part une demi-case au-dessus du plateau avec une vitesse nulle, GRAVITY vaut 0,0055 pixel par milliseconde au carré, et chaque trame applique vy += GRAVITY × dt puis y += vy × dt. Dès que la position dépasse le centre de la case visée, je la fixe exactement à ce centre avant d'appeler settleFallingPiece. Ce recalage compte: laisser la physique décider de la position finale produit des rangées légèrement de travers.

Quatre états gouvernent le reste: ready, playing, dropping et over. Les touches sont ignorées pendant dropping, ce qui règle d'un coup le double coup joué et le changement de colonne en pleine chute. Le delta-time est borné à un trentième de seconde pour qu'un retour d'onglet ne téléporte pas le jeton sous le plateau.

Ce que j'en ai retenu

Ce que je retiens tient en une phrase: le bon moment pour vérifier quelque chose, c'est celui où l'information est encore petite. Le gagnant se décide sur une seule case, celle qui vient d'être remplie, et toute la vérification découle de là.

L'autre chose, c'est la valeur d'un état explicite. Dans mon métier, une passerelle vidéo qui accepte une commande pendant une transition finit toujours par produire un état incohérent. Ici, un jeton qui tombe est un état à part entière, et l'interface n'a plus rien à ignorer manuellement.