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;
+}