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, 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]; } } } return { value: bestValue, move: bestMove }; } 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; } } move(matrix) { if (this.level === 0) { return this.random_move(matrix); } else { return this.evaluate(matrix); } } } 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 gameBoard = document.getElementById('game-board'); gameBoard.innerHTML = ''; 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); }); gameBoard.appendChild(rowElement); }); } 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(); } } 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(); } } const game = new Game(); game.start();