diff --git a/R4.01_R4.A.10/td_tp/tp1/README.md b/R4.01_R4.A.10/td_tp/tp1/README.md index ad33ade..ccb0140 100644 --- a/R4.01_R4.A.10/td_tp/tp1/README.md +++ b/R4.01_R4.A.10/td_tp/tp1/README.md @@ -99,3 +99,42 @@ Par commodité, on note la table de transition précédente simplement : ``` 4. Utilisez la fonction `reduce` pour le calcul du minimum **et** du maximum. + +#### Ex3 : le jeu de la vie + +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) + +Vous disposez des [sources](./src/ex3) à compléter. En particulier, + +- la méthode `setInitialState` qui initialise la grille de départ. Le format en entrée est une chaîne + contenant la liste des cellules vivantes. + ```js + // exemple + 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' + ``` + > Utiliser `split` et `map`. + +- la méthode `getNumberActiveNeighbourgCelles(x,y)` qui calcule le nombre de cellules vivantes voisines + d'une cellule donnée. + > Utiliser `filter` + +- la fonction `computeNextGeneration` qui permet de calculer la génération suivante de cellules de la grille. + +<div align="center"> +<img src="./img/vie.png"> +</div> + +- Ajoutez un bouton `reset` qui permet de recommencer le jeu. +- Ajoutez bouton qui permet d'afficher lors du clic une popin. Vous allez pouvoir renseigner la taille de la grille. +- Affichez le numéro de la génération en cours, ainsi que la taille de la grille. + + +> Vous aurez besoin de la fonction [prompt](https://www.w3schools.com/jsref/met_win_prompt.asp). diff --git a/R4.01_R4.A.10/td_tp/tp1/src/vie/index.html b/R4.01_R4.A.10/td_tp/tp1/src/vie/index.html new file mode 100644 index 0000000..9ff9904 --- /dev/null +++ b/R4.01_R4.A.10/td_tp/tp1/src/vie/index.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html lang="fr"> + + <head> + <meta charset="utf-8"> + <meta name="viewport" content="initial-scale=1,witdh=device-width"> + <link + rel="stylesheet" + href="https://cdn.jsdelivr.net/npm/bulma@1.0.2/css/bulma.min.css" +> + <link rel="stylesheet" href="./style.css"> + <title>Jeu de la vie</title> + </head> + + <body class="has-text-centered m-4"> + <h2 class="title is-2 has-text-primary-dark">Le jeu de la vie</h2> + <nav class="m-2"> + <button class="button" id="next-gen">Prochaine Génération</button> + <button class="button" id="autoplay">Auto Play</button> + <p class="mt-2"> + Génération numéro: <span id="generation-value"></span> | Taille de la grille: <span id="grid-size-value"></span> + </p> + </nav> + <div id="container"></div> + <script src="script.js"></script> + </body> + +</html> diff --git a/R4.01_R4.A.10/td_tp/tp1/src/vie/script.js b/R4.01_R4.A.10/td_tp/tp1/src/vie/script.js new file mode 100644 index 0000000..80fef67 --- /dev/null +++ b/R4.01_R4.A.10/td_tp/tp1/src/vie/script.js @@ -0,0 +1,152 @@ + +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() { + const container = document.getElementById(this.gridContainerId) + container.replaceChildren() + + this.grid = [] + } + + setInitialState(initialState) { + // TODO + } + + 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) { + // TODO + } + + 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:' + + // TODO + } + +// 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) + }, 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 + } + + generation=computeNextGeneration(gridManager,generation) + }) + +} + + +// Le jeu est démarré ici + +main() diff --git a/R4.01_R4.A.10/td_tp/tp1/src/vie/style.css b/R4.01_R4.A.10/td_tp/tp1/src/vie/style.css new file mode 100644 index 0000000..bedf2c4 --- /dev/null +++ b/R4.01_R4.A.10/td_tp/tp1/src/vie/style.css @@ -0,0 +1,12 @@ +.row { + display: flex; + align-items: center; + justify-content: center; +} + +.cell { + width: 1.25rem; + height: 1.25rem; + border: 1px solid black; + box-sizing : border-box; +}