Tableau de score
Plusieurs compteurs côte à côte pour un match ou un jeu de société, avec des noms modifiables et le meneur mis en avant. Le bon exercice pour gérer une liste d'objets plutôt qu'une seule valeur.
- Décrire l'état avec un tableau d'objets
- Recalculer tout l'affichage à partir des données
- Trouver le meneur et gérer l'égalité
Pourquoi un tableau de score ? Au ping-pong, aux cartes ou au Mölkky, on finit toujours par compter sur un bout de papier. Ici, chaque joueur a son nom, son score, ses boutons.
Le vrai changement, c'est l'état : ce n'est plus un nombre, c'est un tableau d'objets. Ajouter un joueur, c'est ajouter un objet. Après chaque action, on redessine tout à partir de ce tableau, et le joueur en tête change de couleur.
Pourquoi en JavaScript simple ? Un tableau, une boucle qui crée les cartes, un calcul de maximum. C'est le premier pas vers ce que font React ou Vue.
L'ÉTAT
Un tableau d'objets : chaque joueur porte son nom et son score.
const joueurs = [ { nom: 'Rouge', score: 0 }, { nom: 'Bleu', score: 0 }, ];LE MENEUR
S'il y a plusieurs joueurs au même score maximum, personne ne mène.
function meneur() { const max = Math.max(...joueurs.map(j => j.score)); const enTete = joueurs.filter(j => j.score === max); return enTete.length === 1 && max > 0 ? enTete[0] : null; }DESSINER
On reconstruit la grille à partir des données, à chaque changement.
function rendre() { const tete = meneur(); const grille = document.getElementById('grille'); grille.innerHTML = ''; joueurs.forEach((j, i) => { const carte = document.createElement('div'); carte.className = 'joueur' + (j === tete ? ' tete' : ''); carte.innerHTML = '<input aria-label="Nom"><b></b><button data-d="-1">−</button><button data-d="1">+</button>'; carte.querySelector('input').value = j.nom; // value et textContent : pas d'injection de HTML carte.querySelector('b').textContent = j.score; carte.dataset.i = i; grille.appendChild(carte); }); }UN SEUL ÉCOUTEUR
document.getElementById('grille').addEventListener('click', e => { const b = e.target.closest('[data-d]'); if (!b) return; const j = joueurs[b.closest('.joueur').dataset.i]; j.score = Math.max(0, j.score + Number(b.dataset.d)); rendre(); });AJOUTER UN JOUEUR
document.getElementById('ajout').addEventListener('click', () => { joueurs.push({ nom: 'Joueur ' + (joueurs.length + 1), score: 0 }); rendre(); });
PIÈGE 1 : Mettre le nom dans innerHTML
Mauvais : '<b>' + j.nom + '</b>'. Un nom comme <img onerror=...> exécute du code.
Correct : créer la structure, puis remplir avec textContent ou value.
PIÈGE 2 : Perdre le focus à chaque clic
Mauvais : tout redessiner sans y penser. Au clavier, le focus disparaît après chaque point.
Correct : remettre le focus sur le bouton équivalent après le rendu, ou ne mettre à jour que la carte concernée.
PIÈGE 3 : Un meneur en cas d'égalité
Mauvais : prendre le premier joueur qui a le score maximum. À 3 partout, Rouge passe en tête sans raison.
Correct : compter combien de joueurs ont le maximum, et n'afficher un meneur que s'il est seul.
- Un score cible : la partie s'arrête quand un joueur atteint 21 ou 50.
- Un historique des manches, avec le total de chacun.
- Des couleurs par joueur, choisies dans la palette du site.
- Gardez la partie dans localStorage pour la reprendre après une coupure, comme le compteur qui se souvient.
- Avec beaucoup de joueurs, ne redessinez que la carte modifiée au lieu de toute la grille.
Le tableau vit dans un useState, et chaque modification crée un nouveau tableau avec map.
Chaque joueur devient un composant Carte, avec une key stable comme un id, pas l'index.
Le meneur se calcule pendant le rendu, sans état séparé.
Chargement des commentaires…