From bba3d1a72d9aa94f744e91c41c9a63544fd644ee Mon Sep 17 00:00:00 2001 From: letuaillon Date: Wed, 26 Apr 2023 09:25:24 +0200 Subject: [PATCH] ajout de message en cas de victoires / draws... --- script.js | 190 ++++++++++++++++++++++++--------------- script1.js | 225 ----------------------------------------------- style.css | 96 ++++++++++++++------ style1.css | 57 ------------ tictactoe.html | 14 ++- tictactoeAI.html | 14 --- 6 files changed, 201 insertions(+), 395 deletions(-) delete mode 100644 script1.js delete mode 100644 style1.css delete mode 100644 tictactoeAI.html diff --git a/script.js b/script.js index 3ac75cf..3475323 100644 --- a/script.js +++ b/script.js @@ -59,69 +59,75 @@ class AI { const random_index = Math.floor(Math.random() * available_moves.length); return available_moves[random_index]; } - minimax(matrix, maximizing) { - const caseStatus = matrix.winner(); - if (caseStatus === 1) return { value: 1, move: null }; - if (caseStatus === 2) return { value: -1, move: null }; - if (matrix.isFull()) return { value: 0, move: null }; - - let bestValue; - let bestMove = null; - const emptyCases = matrix.getEmptyCases(); - - if (maximizing) { - bestValue = -Infinity; - - for (const [row, col] of emptyCases) { - const tempMatrix = matrix.clone(); - tempMatrix.markCase(row, col, 1); - - const { value } = this.minimax(tempMatrix, false); - - if (value > bestValue) { - bestValue = value; - bestMove = [row, col]; - } - } - } else { - bestValue = Infinity; - - for (const [row, col] of emptyCases) { - const tempMatrix = matrix.clone(); - tempMatrix.markCase(row, col, this.player); - - const { value } = this.minimax(tempMatrix, true); - - if (value < bestValue) { - bestValue = value; - bestMove = [row, col]; + minimax(matrix, depth, maximizingPlayer) { + const winner = this.check_winner(matrix); + + if (winner !== 0) { + return winner === this.player ? 10 - depth : depth - 10; + } + + if (matrix.is_full()) { + return 0; + } + + if (depth >= this.level) { + return 0; + } + + const opponent = 3 - this.player; + const currentPlayer = maximizingPlayer ? this.player : opponent; + + let bestScore = maximizingPlayer ? -Infinity : Infinity; + + for (let row = 0; row < 3; row++) { + for (let col = 0; col < 3; col++) { + if (matrix.cases[row][col] === 0) { + matrix.mark(row, col, currentPlayer); + const score = this.minimax(matrix, depth + 1, !maximizingPlayer); + matrix.cases[row][col] = 0; + matrix.marked_case--; + + bestScore = maximizingPlayer ? Math.max(bestScore, score) : Math.min(bestScore, score); } } } - - return { value: bestValue, move: bestMove }; + + return bestScore; } - - evaluate(mainMatrix) { - if (this.level === 0) { - const emptyCases = mainMatrix.getEmptyCases(); - const randomIndex = Math.floor(Math.random() * emptyCases.length); - return emptyCases[randomIndex]; - } else { - const { move } = this.minimax(mainMatrix, false); - return move; + + check_winner(matrix) { + for (let player = 1; player <= 2; player++) { + if (matrix.check_win(player)) { + return player; + } } + return 0; } - - + move(matrix) { - if (this.level === 0) { - return this.random_move(matrix); - } else { - return this.evaluate(matrix); + let bestScore = -Infinity; + let bestMove = null; + + for (let row = 0; row < 3; row++) { + for (let col = 0; col < 3; col++) { + if (matrix.cases[row][col] === 0) { + matrix.mark(row, col, this.player); + const score = this.minimax(matrix, 1, false); + matrix.cases[row][col] = 0; + matrix.marked_case--; + + if (score > bestScore) { + bestScore = score; + bestMove = [row, col]; + } + } + } } + + return bestMove; } + } class Game { @@ -135,32 +141,42 @@ class Game { } updateBoard() { - const gameBoard = document.getElementById('game-board'); - gameBoard.innerHTML = ''; - + const cells = document.querySelectorAll('.cell'); + this.matrix.cases.forEach((row, rowIndex) => { - const rowElement = document.createElement('div'); - rowElement.classList.add('row'); - row.forEach((cell, cellIndex) => { - const cellElement = document.createElement('div'); - cellElement.classList.add('cell'); - cellElement.dataset.mark = cell; - cellElement.addEventListener('click', () => this.handleCellClick(rowIndex, cellIndex)); - rowElement.appendChild(cellElement); + const cellElement = cells[rowIndex * 3 + cellIndex]; + cellElement.classList.remove('x', 'o'); + if (cell === 1) { + cellElement.classList.add('x'); + } else if (cell === 2) { + cellElement.classList.add('o'); + } }); - - gameBoard.appendChild(rowElement); }); } + + displayMessage(messageId) { + const messages = ['p1win', 'p2win', 'aiwin', 'draw']; + messages.forEach((id) => { + const element = document.getElementById(id); + if (id === messageId) { + element.style.display = 'block'; + } else { + element.style.display = 'none'; + } + }); + } + + handleCellClick(row, col) { if (this.running && this.matrix.mark(row, col, this.player)) { if (this.matrix.check_win(this.player)) { - alert(`Le joueur ${this.player} a gagné !`); + this.displayMessage(this.player === 1 ? 'p1win' : 'p2win'); this.running = false; } else if (this.matrix.is_full()) { - alert("Match nul !"); + this.displayMessage('draw'); this.running = false; } else { this.player = 3 - this.player; @@ -169,10 +185,10 @@ class Game { if (ai_row !== null && ai_col !== null) { this.matrix.mark(ai_row, ai_col, this.ai.player); if (this.matrix.check_win(this.ai.player)) { - alert(`L'IA a gagné !`); + this.displayMessage('aiwin'); this.running = false; } else if (this.matrix.is_full()) { - alert("Match nul !"); + this.displayMessage('draw'); this.running = false; } } @@ -182,6 +198,17 @@ class Game { this.updateBoard(); } } + + + setupEventListeners() { + const cells = document.querySelectorAll('[data-cell]'); + cells.forEach((cell, index) => { + const row = Math.floor(index / 3); + const col = index % 3; + cell.addEventListener('click', () => this.handleCellClick(row, col)); + }); + } + start() { this.running = true; @@ -192,9 +219,32 @@ class Game { this.player = 3 - this.player; } this.updateBoard(); + const messages = ['p1win', 'p2win', 'aiwin', 'draw']; + messages.forEach((id) => { + document.getElementById(id).style.display = 'none'; + }); } + } +const cellElements = document.querySelectorAll('[data-cell]'); +cellElements.forEach((cell, index) => { + cell.addEventListener('click', () => { + const row = Math.floor(index / 3); + const col = index % 3; + game.handleCellClick(row, col); + }); +}); + + const game = new Game(); game.start(); +const resetButton = document.getElementById('reset'); +resetButton.addEventListener('click', () => game.start()); + +const aiButton = document.getElementById('ai'); +aiButton.addEventListener('click', () => { + game.gamemode = game.gamemode === 'ai' ? 'player' : 'ai'; + game.start(); +}); diff --git a/script1.js b/script1.js deleted file mode 100644 index 40e8562..0000000 --- a/script1.js +++ /dev/null @@ -1,225 +0,0 @@ -class Matrix { - constructor() { - this.cases = Array(3).fill(null).map(() => Array(3).fill(0)); - this.marked_case = 0; - } - - is_full() { - return this.marked_case === 9; - } - - mark(row, col, player) { - if (this.cases[row][col] === 0) { - this.cases[row][col] = player; - this.marked_case++; - return true; - } - return false; - } - - check_win(player) { - const win_combinations = [ - [[0, 0], [0, 1], [0, 2]], - [[1, 0], [1, 1], [1, 2]], - [[2, 0], [2, 1], [2, 2]], - [[0, 0], [1, 0], [2, 0]], - [[0, 1], [1, 1], [2, 1]], - [[0, 2], [1, 2], [2, 2]], - [[0, 0], [1, 1], [2, 2]], - [[0, 2], [1, 1], [2, 0]], - ]; - - return win_combinations.some(combination => - combination.every(([row, col]) => this.cases[row][col] === player) - ); - } -} - -class AI { - constructor(level = 5, player = 2) { - this.level = level; - this.player = player; - } - - random_move(matrix) { - const available_moves = []; - - matrix.cases.forEach((row, i) => { - row.forEach((cell, j) => { - if (cell === 0) { - available_moves.push([i, j]); - } - }); - }); - - if (available_moves.length === 0) { - return null; - } - - const random_index = Math.floor(Math.random() * available_moves.length); - return available_moves[random_index]; - } - - minimax(matrix, depth, maximizingPlayer) { - const winner = this.check_winner(matrix); - - if (winner !== 0) { - return winner === this.player ? 10 - depth : depth - 10; - } - - if (matrix.is_full()) { - return 0; - } - - if (depth >= this.level) { - return 0; - } - - const opponent = 3 - this.player; - const currentPlayer = maximizingPlayer ? this.player : opponent; - - let bestScore = maximizingPlayer ? -Infinity : Infinity; - - for (let row = 0; row < 3; row++) { - for (let col = 0; col < 3; col++) { - if (matrix.cases[row][col] === 0) { - matrix.mark(row, col, currentPlayer); - const score = this.minimax(matrix, depth + 1, !maximizingPlayer); - matrix.cases[row][col] = 0; - matrix.marked_case--; - - bestScore = maximizingPlayer ? Math.max(bestScore, score) : Math.min(bestScore, score); - } - } - } - - return bestScore; - } - - check_winner(matrix) { - for (let player = 1; player <= 2; player++) { - if (matrix.check_win(player)) { - return player; - } - } - return 0; - } - - move(matrix) { - let bestScore = -Infinity; - let bestMove = null; - - for (let row = 0; row < 3; row++) { - for (let col = 0; col < 3; col++) { - if (matrix.cases[row][col] === 0) { - matrix.mark(row, col, this.player); - const score = this.minimax(matrix, 1, false); - matrix.cases[row][col] = 0; - matrix.marked_case--; - - if (score > bestScore) { - bestScore = score; - bestMove = [row, col]; - } - } - } - } - - return bestMove; - } - -} - -class Game { - constructor() { - this.matrix = new Matrix(); - this.ai = new AI(); - this.player = 1; - this.gamemode = 'ai'; - this.running = true; - this.ai_starts = false; - } - - updateBoard() { - const cells = document.querySelectorAll('.cell'); - - this.matrix.cases.forEach((row, rowIndex) => { - row.forEach((cell, cellIndex) => { - const cellElement = cells[rowIndex * 3 + cellIndex]; - cellElement.classList.remove('x', 'o'); - if (cell === 1) { - cellElement.classList.add('x'); - } else if (cell === 2) { - cellElement.classList.add('o'); - } - }); - }); - } - - - - - handleCellClick(row, col) { - if (this.running && this.matrix.mark(row, col, this.player)) { - if (this.matrix.check_win(this.player)) { - alert(`Le joueur ${this.player} a gagné !`); - this.running = false; - } else if (this.matrix.is_full()) { - alert("Match nul !"); - this.running = false; - } else { - this.player = 3 - this.player; - if (this.gamemode === 'ai' && this.player === this.ai.player) { - const [ai_row, ai_col] = this.ai.move(this.matrix); - if (ai_row !== null && ai_col !== null) { - this.matrix.mark(ai_row, ai_col, this.ai.player); - if (this.matrix.check_win(this.ai.player)) { - alert(`L'IA a gagné !`); - this.running = false; - } else if (this.matrix.is_full()) { - alert("Match nul !"); - this.running = false; - } - } - this.player = 3 - this.player; - } - } - this.updateBoard(); - } - } - - setupEventListeners() { - const cells = document.querySelectorAll('[data-cell]'); - cells.forEach((cell, index) => { - const row = Math.floor(index / 3); - const col = index % 3; - cell.addEventListener('click', () => this.handleCellClick(row, col)); - }); - } - - - start() { - this.running = true; - this.matrix = new Matrix(); - if (this.gamemode === 'ai' && this.ai_starts) { - const [ai_row, ai_col] = this.ai.move(this.matrix); - this.matrix.mark(ai_row, ai_col, this.ai.player); - this.player = 3 - this.player; - } - this.updateBoard(); - this.setupEventListeners(); - } - -} - -const game = new Game(); -game.start(); - -const resetButton = document.getElementById('reset'); -resetButton.addEventListener('click', () => game.start()); - -const aiButton = document.getElementById('ai'); -aiButton.addEventListener('click', () => { - game.gamemode = game.gamemode === 'ai' ? 'player' : 'ai'; - game.start(); -}); diff --git a/style.css b/style.css index 4ccf8d6..f26c395 100644 --- a/style.css +++ b/style.css @@ -1,48 +1,94 @@ body { - font-family: Arial, sans-serif; display: flex; - flex-direction: column; + justify-content: center; align-items: center; - background-color: #f0f0f0; + height: 100vh; + margin: 0; + background-color: #1E2125; + font-family: "Arial", sans-serif; } -h1 { - margin-bottom: 1rem; -} - -#game-board { +.container { display: flex; flex-direction: column; - width: 300px; - height: 300px; - background-color: white; - border: 1px solid black; + align-items: center; } -.row { - display: flex; - flex-direction: row; - height: 33.33%; +.grid { + display: grid; + grid-template-columns: repeat(3, 100px); + grid-template-rows: repeat(3, 100px); + gap: 15px; + margin-bottom: 25px; } .cell { + width: 100px; + height: 100px; display: flex; justify-content: center; align-items: center; - width: 33.33%; - height: 100%; - border: 1px solid black; + background-color: #2C3036; + color: #FFFFFF; + font-size: 24px; + font-weight: bold; cursor: pointer; } -.cell[data-mark="1"]::before { +button { + padding: 10px 20px; + background-color: #1E2125; + color: #FFFFFF; + border: 2px solid #FFFFFF; + font-size: 16px; + cursor: pointer; + margin: 5px; +} + +button:hover { + background-color: #2C3036; +} +.cell.x::after { content: "X"; - font-size: 2rem; - color: #2196F3; + color: #4fb2d3; } -.cell[data-mark="2"]::before { +.cell.o::after { content: "O"; - font-size: 2rem; - color: #F44336; + color: #b40e0e; } +h1{ + color: #FFFFFF; + font-size: 24px; + font-weight: bold; + margin: 0; + margin-bottom: 25px; +} + +.winnerMessage { + color: #FFFFFF; + font-size: 18px; + font-weight: bold; + margin: 0; + margin-bottom: 15px; +} + +#aiwin { + color: #b40e0e; + display: none; +} + +#p1win { + color: #4fb2d3; + display: none; +} + +#p2win { + color: #b40e0e; + display: none; +} + +#draw { + color: #FFFFFF; + display: none; +} \ No newline at end of file diff --git a/style1.css b/style1.css deleted file mode 100644 index 64991b6..0000000 --- a/style1.css +++ /dev/null @@ -1,57 +0,0 @@ -body { - display: flex; - justify-content: center; - align-items: center; - height: 100vh; - margin: 0; - background-color: #1E2125; - font-family: "Arial", sans-serif; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; -} - -.grid { - display: grid; - grid-template-columns: repeat(3, 100px); - grid-template-rows: repeat(3, 100px); - gap: 15px; - margin-bottom: 25px; -} - -.cell { - width: 100px; - height: 100px; - display: flex; - justify-content: center; - align-items: center; - background-color: #2C3036; - color: #FFFFFF; - font-size: 24px; - font-weight: bold; - cursor: pointer; -} - -button { - padding: 10px 20px; - background-color: #1E2125; - color: #FFFFFF; - border: 2px solid #FFFFFF; - font-size: 16px; - cursor: pointer; - margin: 5px; -} - -button:hover { - background-color: #2C3036; -} -.cell.x::after { - content: "X"; -} - -.cell.o::after { - content: "O"; -} diff --git a/tictactoe.html b/tictactoe.html index 3e2ace6..5066ab4 100644 --- a/tictactoe.html +++ b/tictactoe.html @@ -4,10 +4,12 @@ Tic Tac Toe - IA - + +
+

Tic Tac Toe - AI

@@ -19,9 +21,13 @@
- - +
Player 1 won
+
Player 2 won
+
IA won
+
There is equality
+ +
- + diff --git a/tictactoeAI.html b/tictactoeAI.html deleted file mode 100644 index 99dfded..0000000 --- a/tictactoeAI.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - Jeu de Morpion - - - -

Jeu de Morpion

-
- - -