diff --git a/TicTacToe.py b/TicTacToe.py index d1928f4..8b2827d 100644 --- a/TicTacToe.py +++ b/TicTacToe.py @@ -92,7 +92,7 @@ class Matrix: #Class : AI class AI: - def __init__(self, level= 5, player=2): + def __init__(self, level= 1, player=2): self.level = level self.player = player diff --git a/__pycache__/constants.cpython-39.pyc b/__pycache__/constants.cpython-39.pyc new file mode 100644 index 0000000..b401ac6 Binary files /dev/null and b/__pycache__/constants.cpython-39.pyc differ diff --git a/script1.js b/script1.js index 1339d6c..012104e 100644 --- a/script1.js +++ b/script1.js @@ -1,136 +1,162 @@ -const cells = document.querySelectorAll('.cell'); -const resetButton = document.querySelector('#reset'); -const aiButton = document.querySelector('#toggle-ai'); - -let board = Array.from({ length: 9 }, () => 0); -let currentPlayer = 1; -let aiEnabled = true; -let gameMode = 'ai'; -let running = true; - -function handleClick(e) { - const cell = e.target; - const index = cells.findIndex(c => c === cell); - - if (board[index] !== 0 || !running) { - return; +class Matrix { + constructor() { + this.cases = Array(3).fill(null).map(() => Array(3).fill(0)); + this.marked_case = 0; } - makeMove(index); - - if (checkWinner(board) !== 0 || board.every(cell => cell !== 0)) { - running = false; + is_full() { + return this.marked_case === 9; } - if (running && gameMode === 'ai' && currentPlayer === 2) { - const { move } = minimax(board, false); - makeMove(move); - - if (checkWinner(board) !== 0 || board.every(cell => cell !== 0)) { - running = false; + mark(row, col, player) { + if (this.cases[row][col] === 0) { + this.cases[row][col] = player; + this.marked_case++; + return true; } + return false; } -} - -function makeMove(index) { - board[index] = currentPlayer; - cells[index].textContent = currentPlayer === 1 ? 'X' : 'O'; - currentPlayer = 3 - currentPlayer; -} - -function isRunning() { - return !checkWinner(board) && board.some(cell => cell === 0); -} -function checkWinner(tempBoard) { - const winningCombinations = [ - [0, 1, 2], - [3, 4, 5], - [6, 7, 8], - [0, 3, 6], - [1, 4, 7], - [2, 5, 8], - [0, 4, 8], - [2, 4, 6], - ]; - - for (const combination of winningCombinations) { - const [a, b, c] = combination; - if (tempBoard[a] !== 0 && tempBoard[a] === tempBoard[b] && tempBoard[a] === tempBoard[c]) { - return tempBoard[a]; - } + 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) + ); } - - return 0; } -function checkGameOver() { - const winner = checkWinner(board); - if (winner !== 0) { - alert(`Le joueur ${winner} a gagné !`); - } else if (!isRunning()) { - alert('Match nul !'); +class AI { + constructor(level = 5, player = 2) { + this.level = level; + this.player = player; } -} -function resetBoard() { - board = Array.from({ length: 9 }, () => 0); - currentPlayer = 1; - running = true; - cells.forEach(cell => (cell.textContent = '')); -} + random_move(matrix) { + const available_moves = []; -function toggleAi() { - aiEnabled = !aiEnabled; - gameMode = aiEnabled ? 'ai' : '1v1'; -} + matrix.cases.forEach((row, i) => { + row.forEach((cell, j) => { + if (cell === 0) { + available_moves.push([i, j]); + } + }); + }); -function minimax(tempBoard, maximizing) { - const winner = checkWinner(tempBoard); + if (available_moves.length === 0) { + return null; + } - if (winner !== 0) { - return { eval: winner === 1 ? 1 : -1, move: null }; - } else if (!tempBoard.some(cell => cell === 0)) { - return { eval: 0, move: null }; + const random_index = Math.floor(Math.random() * available_moves.length); + return available_moves[random_index]; } - let bestEval, bestMove; + - if (maximizing) { - bestEval = -Infinity; + move(matrix) { + return this.random_move(matrix); + } +} - for (let i = 0; i < tempBoard.length; i++) { - if (tempBoard[i] === 0) { - const newBoard = [...tempBoard]; - newBoard[i] = 1; +class Game { + constructor() { + this.matrix = new Matrix(); + this.ai = new AI(); + this.player = 1; + this.gamemode = 'ai'; + this.running = true; + this.ai_starts = false; + } - const eval = minimax(newBoard, false).eval; - if (eval > bestEval) { - bestEval = eval; - bestMove = i; + 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'); } - } - } - } else { - bestEval = Infinity; - - for (let i = 0; i < tempBoard.length; i++) { - if (tempBoard[i] === 0) { - const newBoard = [...tempBoard]; - newBoard[i] = 2; - - const eval = minimax(newBoard, true).eval; - if (eval < bestEval) { - bestEval = eval; - bestMove = i; + }); + }); + } + + + + + 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(); } } - - return { eval: bestEval, move: bestMove }; + + 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(); + } + } -cells.forEach(cell => cell.addEventListener('click', handleClick)); -resetButton.addEventListener('click', resetBoard); -aiButton.addEventListener('click', toggleAi); +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/style1.css b/style1.css index 3962ed1..64991b6 100644 --- a/style1.css +++ b/style1.css @@ -48,3 +48,10 @@ button { button:hover { background-color: #2C3036; } +.cell.x::after { + content: "X"; +} + +.cell.o::after { + content: "O"; +} diff --git a/tictactoe.html b/tictactoe.html index 91d1fee..3e2ace6 100644 --- a/tictactoe.html +++ b/tictactoe.html @@ -22,6 +22,6 @@ - +