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 : + + + +### 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();