From 4625ec8e2ce38d251ad75258f34bfcf9b90ad671 Mon Sep 17 00:00:00 2001
From: Denis Monnerat <monnerat@u-pec.fr>
Date: Tue, 17 Dec 2024 09:32:21 +0100
Subject: [PATCH] ajout tp5

---
 R1.02/tp/tp5/README.md      |  98 +++++++++++++++++
 R1.02/tp/tp5/img/jeu.png    | Bin 0 -> 10512 bytes
 R1.02/tp/tp5/src/index.html |  44 ++++++++
 R1.02/tp/tp5/src/script.js  | 207 ++++++++++++++++++++++++++++++++++++
 4 files changed, 349 insertions(+)
 create mode 100644 R1.02/tp/tp5/README.md
 create mode 100644 R1.02/tp/tp5/img/jeu.png
 create mode 100644 R1.02/tp/tp5/src/index.html
 create mode 100644 R1.02/tp/tp5/src/script.js

diff --git a/R1.02/tp/tp5/README.md b/R1.02/tp/tp5/README.md
new file mode 100644
index 0000000..d0d9b2c
--- /dev/null
+++ b/R1.02/tp/tp5/README.md
@@ -0,0 +1,98 @@
+<h1> TP Js 1</h1>
+
+
+> Récupérez les fichiers sources utilisés pour le tp [ici](src/).
+
+## Exercices
+
+Le TP est une implantation en javasript du jeu de la vie. Il s'agit d'un automate cellulaire, dont les règles sont les suivantes : 
+ - Une cellule morte possédant exactement trois voisines vivantes devient vivante. 
+ - Une cellule vivante possédant deux ou trois voisines vivantes reste vivante, sinon elle meurt.
+
+Une cellule est une unité de la grille (carrée). Un tour est appelé une génération.
+
+
+>Pour plus d'informations, voir la page [Wikipédia](https://fr.wikipedia.org/wiki/Jeu_de_la_vie)
+
+> Le jeu est déjà codé, vous allez ajouter de nouvelles fonctionnalités au jeu dans ce TP.
+
+### Exercice 1 : Inclure du JS
+
+Chargez le fichier `script.js` dans la page html `index.html`
+
+> Il faut utiliser la balise `<script>` avec l'attribut `src` <br>
+> Attention ! Chargez le fichier  une fois que le DOM (la page HTML) est chargée. 
+
+Vous devez avoir le résultat suivant : 
+
+![gallerie](img/jeu.png ':-:')
+
+### Exercice 2 : Ajouter un bouton reset
+
+Ajoutez un bouton `reset` dans le HTML. Dans la fonction `main()` ajoutez ce qui est nécessaire pour pourvoir remettre à zéro le jeu. <br>
+
+> Pour remettre à zéro, il faut s'abonner à l'événement `click` sur le bouton reset, regardez comment le code est fait pour les autres boutons. <br>
+> Il faut ensuite:
+>  - stopper `autoplayInterval`, un timer est démarré avec la fonctionnalité auto play
+>  - détruire la grille courante avec la fonction `gridManager.destroyGrid();`
+>  - créer un nouvel object `GridManager` avec `gridManager = new GridManager(gridSize, DIV_CONTAINER_ID)`
+>  - initialiser le jeu avec `gridManager.setInitialState(INITIAL_STATE)`
+><br><br>
+
+> Vous avez des exemples dans le code.
+
+
+### Exercice 3 : Changer la taille de la grille
+
+Vous allez ajouter un bouton qui permet d'afficher lors du clic une popin. Vous allez pouvoir renseigner la taille de la grille. 
+
+> - Vous aurez besoin de la fonction [prompt](https://www.w3schools.com/jsref/met_win_prompt.asp).
+> - La valeur que vous récupérer est un type `string` (équivalent à char[] en C), il faut donc parser le type string en integer avec la fonction [parseInt()](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/parseInt)
+> - Vous allez réutiliser la fonction reset que vous avez écrite précédemment.
+
+> La grille est d'une taille minimum de 30.
+
+
+### Exercice 4 : Afficher la taille de la grille dans l'interface
+
+Vous allez afficher la taille à côté de la chaine de caractères `Taille de la grille:`. 
+
+> - Utilisez `document.getElementById(GRID_SIZE_VAL_ID)` 
+> - Utilisez la propriété `element.textContent = 'Hello World!`
+
+### Exercice 5 : Afficher la génération courante
+
+Vous allez afficher le numéro de la génération courante à côté de la chaine de caractères `Génération numéro:`. 
+
+> - Ajoutez ce qu'il manque dans la fonction `computeNextGeneration(gridManager, generation)`
+> - Pensez à incrémenter la variable `génération`
+
+### Exercice 6 : Vitesse d'execution du jeu
+
+Vous allez créer un bouton : 
+ - x1
+ - x2
+ - x10
+ - x100
+
+Lorsque le jeu est en mode auto play, il faut changer la vitesse à laquelle il faut appeler la fonction `computeNextGeneration(gridManager, generation)`. Si le jeu n'est pas en mode auto play mettre à jour la valeur de interval
+
+> - Il faut pensez à stopper le `setInterval` et le démarrer avec la nouvelle vitesse de jeu
+> - La vitesse normale du jeu est défini par la variable `GENERATION_INTERVAL`
+> - x2 = `GENERATION_INTERVAL/2`, x10 = `GENERATION_INTERVAL/10`, etc.  
+
+### Exercice 7 : (Bonus) Export de l'état de la grille
+
+On veut pouvoir sauvegarder la partie pour la reprendre plus tard. Pour cela il faut enregistrer l'état du jeu. <br>
+
+Créez une fonction d'export qui permet de : 
+ - récupérez la taille de la grille, connaitre les coordonnées des cellules actives, la génération courante et la vitesse d'éxecution du jeu si mode auto play
+ - sauvegardez l'état du jeu en `localStorage` lorsque l'on clique sur un bouton `Sauvegarder`
+
+
+ > - Réutilisez la fonction `logCurrentGridState` qui permet d'afficher les coordonnées des cellules actives dans la console
+ > - Un peu d'aide sur le [localStorage](https://developer.mozilla.org/fr/docs/Web/API/Window/localStorage)
+
+### Exercice 8 : (Bonus) Reprendre une partie
+
+A partir de l'exercice 7, écrire une fonction qui permet de reprendre une partie lorsque l'on clique sur un bouton `Reprendre` et si des données sont stockées en localStorage. 
diff --git a/R1.02/tp/tp5/img/jeu.png b/R1.02/tp/tp5/img/jeu.png
new file mode 100644
index 0000000000000000000000000000000000000000..45863473237df575f6fdabb085ab5678bb6c0e26
GIT binary patch
literal 10512
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
Jmvv4FO#poSLN5RS

literal 0
HcmV?d00001

diff --git a/R1.02/tp/tp5/src/index.html b/R1.02/tp/tp5/src/index.html
new file mode 100644
index 0000000..e47af8e
--- /dev/null
+++ b/R1.02/tp/tp5/src/index.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html lang="fr">
+
+	<head>
+		<meta charset="utf-8">
+		<meta name="viewport" content="initial-scale=1,witdh=device-width">  
+		<title>Jeu de la vie</title>
+		<style>
+	* {
+		font-size : 1.1rem;
+	}
+	.menu {
+		text-align: center;
+	}
+
+	.row {
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.cell {
+		width: 1.25rem;
+		height: 1.25rem;
+		border: 1px solid black;
+		box-sizing : border-box;
+	}
+		</style>
+	</head>
+
+	<body>
+		<menu class="menu">
+			<button id="next-gen">Prochaine Génération</button>
+			<button id="autoplay">Auto Play</button>
+			<p>
+			Génération numéro: <span id="generation-value"></span> | Taille de la grille: <span id="grid-size-value"></span>
+			</p>
+		</menu>
+
+		<div id="container"></div>
+		<script src="script.js"></script>
+	</body>
+
+</html>
diff --git a/R1.02/tp/tp5/src/script.js b/R1.02/tp/tp5/src/script.js
new file mode 100644
index 0000000..cd5bcb1
--- /dev/null
+++ b/R1.02/tp/tp5/src/script.js
@@ -0,0 +1,207 @@
+// ---------------------------------------------------------------------
+// ---------------------------------------------------------------------
+
+/**
+ * Cette partie du code, vous n'avez pas besoin d'y toucher. Elle permet 
+ * de gérer la grille et l'affichage des cellules
+ */
+
+class GridManager {
+  ACTIVE_COLOR = 'black';
+  INACTIVE_COLOR = 'grey';
+
+  gridContainerId;
+  gridSize;
+  grid = [];
+
+  constructor(gridSize, gridContainerId) {
+    if (!gridSize || gridSize < 30) {
+      throw new Error('The grid size must be at least 30');
+    }
+
+    if (!gridContainerId) {
+      throw new Error('gridContainerId must be set');
+    }
+
+    this.gridSize = gridSize;
+    this.gridContainerId = gridContainerId;
+    this.createGrid();
+  }
+
+  createGrid() {
+    const container = document.getElementById(this.gridContainerId);
+  
+    for (let i = 0; i < this.gridSize; i++) {
+      const row = document.createElement('div');
+      row.className = 'row';
+  
+      const gridRow = [];
+  
+      for (let j = 0; j < this.gridSize; j++) {
+        const cell = document.createElement('div');
+        cell.className = 'cell';
+        cell.style.backgroundColor = this.INACTIVE_COLOR;
+        row.appendChild(cell);
+  
+        gridRow.push(cell);
+      }
+  
+      container.appendChild(row);
+      this.grid.push(gridRow);
+    }
+  }
+
+  destroyGrid() {
+    for (let x = 0; x < this.gridSize; x++) {
+      for (let y = 0; y < this.gridSize; y++) {
+        const node = this.grid[y][x];
+        node.parentNode.removeChild(node);
+      }
+    }
+
+    const container = document.getElementById(this.gridContainerId);
+    while (container.firstChild) {
+      container.removeChild(container.lastChild);
+    }
+
+    this.grid = [];
+  }
+
+  setInitialState(initialState) {
+    const coords = initialState.split(';').map(coord => coord.split(','));
+    coords.forEach((coord) => this.activeCell(+coord[0], +coord[1]));
+  }
+
+  isInGridRange(x, y) {
+    return x >= 0 && x < this.gridSize && y >= 0 && y < this.gridSize;
+  }
+
+  isActiveCell(x, y) {
+    return this.isInGridRange(x, y) && this.grid[y][x].style.backgroundColor === this.ACTIVE_COLOR;
+  }
+
+  activeCell(x, y) {
+    if (!this.isInGridRange(x, y)) {
+      return;
+    }
+
+    this.grid[y][x].style.backgroundColor = this.ACTIVE_COLOR;
+  }
+  
+  deactiveCell(x, y) {
+    if (!this.isInGridRange(x, y)) {
+      return;
+    }
+    
+    this.grid[y][x].style.backgroundColor = this.INACTIVE_COLOR;
+  }
+  
+  getNumberActiveNeighbourCells(x, y) {
+    const neighbours = [
+      [x-1, y-1], [x, y-1], [x+1, y-1],
+      [x-1, y],             [x+1, y],
+      [x-1, y+1], [x, y+1], [x+1, y+1],
+    ];
+  
+    return neighbours.map(cell => this.isActiveCell(cell[0], cell[1])).filter(cell => cell === true).length; 
+  }
+
+  logCurrentGridState() {
+    const activeCells = [];
+  
+    for (let x = 0; x < this.gridSize; x++) {
+      for (let y = 0; y < this.gridSize; y++) {
+        if (this.isActiveCell(x, y)) {
+          activeCells.push(`${x},${y}`);
+        }
+      }
+    }
+  
+    console.log(activeCells.join(';'));
+  }
+}
+
+
+// ---------------------------------------------------------------------
+// ---------------------------------------------------------------------
+
+
+const INITIAL_STATE = '11,1;12,1;10,2;9,3;9,4;9,5;10,6;11,7;12,7;2,4;1,5;2,5;18,28;17,28;19,27;20,26;20,25;20,24;19,23;18,22;17,22;27,25;28,24;27,24;11,28;12,28;10,27;9,26;9,25;9,24;10,23;11,22;12,22;2,25;1,24;2,24;18,1;17,1;19,2;20,3;20,4;20,5;19,6;18,7;17,7;27,4;28,5;27,5';
+const GENERATION_INTERVAL = 1000; // 1 seconde
+const DIV_CONTAINER_ID = 'container'; 
+const BTN_AUTOPLAY_ID = 'autoplay';
+const BTN_NEXT_GEN_ID = 'next-gen';
+const GENERATION_VAL_ID = 'generation-value';
+const GRID_SIZE_VAL_ID = 'grid-size-value';
+
+function computeNextGeneration(gridManager, generation) 
+{
+
+  // incrémenter la valeur de la génération et l'afficher à côté de 'Génération numéro:'
+
+  const nextGrid = [];
+
+  for (let x = 0; x < gridManager.gridSize; x++) {
+    const row = [];
+    for (let y = 0; y < gridManager.gridSize; y++) {
+      const isActive = gridManager.isActiveCell(x, y);
+      const numberActiveNeighbourCells = gridManager.getNumberActiveNeighbourCells(x, y);
+
+      if (!isActive) {
+        row.push(numberActiveNeighbourCells === 3 ? true : false);
+      } else {
+        row.push(numberActiveNeighbourCells === 2 || numberActiveNeighbourCells === 3 ? true : false);
+      }
+    }
+
+    nextGrid.push(row);
+  }
+
+  for (let x = 0; x < nextGrid.length; x++) {
+    for (let y = 0; y < nextGrid[x].length; y++) {
+      nextGrid[x][y] ? gridManager.activeCell(x,y) : gridManager.deactiveCell(x,y);
+    }
+  }
+
+  gridManager.logCurrentGridState();
+  return generation;
+}
+
+// Fonction principale du jeu
+
+function main() 
+{
+  let autoplayInterval;
+  let gridSize = 30;
+  let generation = 0;
+
+  let gridManager = new GridManager(gridSize, DIV_CONTAINER_ID);
+  gridManager.setInitialState(INITIAL_STATE);
+  
+  // Lorsqu'un utilisateur clique sur 'Auto Play'
+  document.getElementById(BTN_AUTOPLAY_ID).addEventListener('click', () => {
+    if (autoplayInterval) {
+      return;
+    }
+  
+    autoplayInterval = setInterval(() => {
+      generation = computeNextGeneration(gridManager);
+    }, GENERATION_INTERVAL);
+  });
+
+  // Lorsqu'un utilisateur clique sur 'Prochaine Génération'
+	document.getElementById(BTN_NEXT_GEN_ID).addEventListener('click', () => {
+		if (autoplayInterval) {
+			clearInterval(autoplayInterval);
+			autoplayInterval = null;
+		}
+
+		computeNextGeneration(gridManager);
+	});
+
+}
+
+
+// Le jeu est démarré ici
+
+main();