Labo - Jeu#
Introduction#
Pendant ce labo, vous allez développer la version "Lights In", du jeu "Light Out" dont le but est d'allumer toutes les cellules.
Règle du jeu:
Lorsqu'on clique sur une cellule, celle-ci change d'état ainsi que ses quatre
voisines (au sud, à l'est, au nord et à l'ouest), si elles existent.
Programmation#
En vous aidant de l'exemple 1, programmez les étapes ci-dessous dans l'ordre.
En utilisant les éléments HTML appropriés, commencez par créer la page statique de votre jeu avec un titre, les règles du jeu, ainsi que le but. Ajoutez un tableau de dimension 3x3.
Astuce
Utilisez un tableau sans entête.
Ajoutez du style à votre page pour que:
le tableau ait des bordures,
la hauteur et la largeur des cellules soient de 50px,
la couleur de fond des cellules soit d'une autre couleur,
le tableau soit centré.
Astuce
Utilisez des sélecteurs de type.
Pour que le tableau soit centré, les marges à droite et à gauche doivent être automatiques.
Les différents propriétés nécessaires sont:
border
, border-collapse
, width
, height
, margin-left
, margin-right
,
margin-top
Dans la partie script, ajoutez la fonctionnalité suivante en définissant la
fonction changeEtat(event)
:
Lorsque vous cliquez sur une cellule du tableau, le texte "clic" doit s'afficher dans celle-ci. Cela permettra de vérifier que les clics dans les cellules sont correctement détectés.
Astuce
Pour que les clics sur les cellules soient détectés, utilisez
addEventListener
sur chaque cellule. Pour éviter les répétitions, stockez toutes les cellules dans une liste et faites une boucle sur chaque élément (cf exemple 1).La fonction
changeEtat(event)
a un paramètreevent
qui est déclenché par le clic de la souris (ou du touchpad).function changeEtat(event) { const c = event.target; // récupère l'élément html ciblé par le clic ...
Modifiez la fonction changeEtat(event)
pour que lorsque vous cliquez sur une
cellule, celle-ci change d'état. Si elle est allumée (colorée), elle s'éteint
(sans couleur de fond) et vice-versa.
Astuce
Trouvez la propriété qui permet de changer la couleur de fond d'une cellule.
Pour changer la couleur d'une cellule, utiliser une classe "allume".
dans la partie style, définissez le style de la classe "allume" (choisissez une couleur de fond).
.allume { /* complétez par la propriété et la valeur désirée */ }
ajoutez la classe "allume" au
<td>
de la cellule pour l'allumer et en la supprimant pour l'éteindre. Cela se fait au moyen de:c.classList.toggle("allume"); // ajoute la classe "allume" à l'élément ou l'efface
Ce code doit remplacer
c.textContent = "clic"
.
Ajoutez la fonctionnalité suivante:
Au début du jeu, l'état des cellules doit être déterminé de manière aléatoire.
Astuce
La fonction Math.random()
renvoie un nombre à virgule pseudo-aléatoire compris
dans l'intervalle [0, 1[.
Parcourez toutes les cellules (ce que vous avez déjà programmé à l'étape 3) et
colorez-en certaines en utilisant la fonction Math.random()
et en leur
ajoutant la classe "allume".
c.classList.add("allume"); // ajoute la classe entre parenthèse à l'élément c
Programmez la fin de la partie, c'est-à-dire le moment où toutes les cellules sont allumées:
Définissez une fonction
gagne(liste)
qui teste si toutes les cellules sont allumées.Après avoir changé l'état des cellules, vérifiez si la partie est gagnée.
Si c'est le cas, affichez le message de victoire.
Astuce
Dans la fonction
gagne
, parcourez la liste des cellules et dès qu'une cellule n'est pas allumée, renvoyezFalse
(le but n'est pas atteint). À la fin de la fonction, renvoyezTrue
(toutes les cellules sont allumées).Pour afficher du texte sur la page, regardez l'affichage de l'erreur dans l'exemple 1.
Modifiez la fonction changeEtat(event)
pour qu'elle suive la règle du jeu,
c'est-à-dire qu'elle modifie aussi les 4 cellules voisines (au nord, sud, est et
ouest).
Astuce
Il est plus facile de travailler avec des coordonnées x et y pour le tableau plutôt que d'utiliser l'index. Voici le code qui permet de convertir l'index en coodonnées x et y:
const c = event.target; // retourne l'élément ciblé
const index = cellules.indexOf(c); // retourne l'index de l'élément ciblé
const x = index % larg; // calcule la coordonnée x en fonction de l'index
const y = Math.trunc(index / larg); // calcule la coordonnée y en fonction de l'index
Et celui pour convertir les coordonnées x et y en index:
function changeCoordEnIndex(x, y) {
return y * larg + x;
}
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Création d'un jeu</title>
<style>
/* Ajout des styles CSS */
</style>
</head>
<body>
<!-- Ajout des éléments HTML -->
<script>
/* Ajout du JavaScript */
</script>
</body>
</html>
Solution
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Création d'un jeu</title>
<style>
table {
margin-top: 1em;
border: 1px solid black;
border-collapse: collapse;
margin-left:auto;
margin-right:auto;
}
td {
border: 1px solid black;
width: 50px;
height: 50px;
}
.allume {
background: yellow;
}
#gagne {
margin-top: 1em;
text-align: center;
font-weight: bold;
color: #c71585;
}
</style>
</head>
<body>
<h1>Création d'un jeu</h1>
<h2>Règles du jeu</h2>
<p>Lorsqu'on clique sur une case, celle-ci change d'état ainsi que ses quatre
voisines (au sud, à l'est, au nord et à l'ouest), si elles existent.</p>
<h2>But</h2>
<p>Allumer toutes les cellules.</p>
<table class="cellules">
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
<div id="gagne"></div>
<script>
const larg = 3, haut = 3;
const cellules = [...document.querySelectorAll(".cellules td")];
function changeCoordEnIndex(x, y) {
return y * larg + x;
}
function gagne(liste) {
for (const c of liste) {
if (!c.classList.contains("allume")) {
return false;
}
}
return true;
}
/* change l'état de la case cliquée */
function changeEtat(event) {
const c = event.target;
const index = cellules.indexOf(c);
const x = index % larg;
const y = Math.trunc(index / larg);
cellules[changeCoordEnIndex(x, y)].classList.toggle("allume");
/* Vérifie qu'on n'est pas sur la première ligne */
if (y > 0) {
cellules[changeCoordEnIndex(x, y - 1)].classList.toggle("allume");
}
/* Vérifie qu'on n'est pas sur la dernière ligne */
if (y < haut - 1) {
cellules[changeCoordEnIndex(x, y + 1)].classList.toggle("allume");
}
if (x > 0) {
cellules[changeCoordEnIndex(x - 1, y)].classList.toggle("allume");
}
if (x < larg - 1) {
cellules[changeCoordEnIndex(x + 1, y)].classList.toggle("allume");
}
if (gagne(cellules)) {
document.getElementById("gagne").textContent = "Bravo, tu as gagné!"
}
}
/* boucle sur toutes les cellules pour les initaliser */
for (const c of cellules) {
c.addEventListener("click", changeEtat);
if (Math.random() < 0.5) {
c.classList.add("allume");
}
}
</script>
</body>
</html>