You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
3.4 KiB
137 lines
3.4 KiB
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;
|
|
}
|
|
|
|
makeMove(index);
|
|
|
|
if (checkWinner(board) !== 0 || board.every(cell => cell !== 0)) {
|
|
running = false;
|
|
}
|
|
|
|
if (running && gameMode === 'ai' && currentPlayer === 2) {
|
|
const { move } = minimax(board, false);
|
|
makeMove(move);
|
|
|
|
if (checkWinner(board) !== 0 || board.every(cell => cell !== 0)) {
|
|
running = 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];
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
function checkGameOver() {
|
|
const winner = checkWinner(board);
|
|
if (winner !== 0) {
|
|
alert(`Le joueur ${winner} a gagné !`);
|
|
} else if (!isRunning()) {
|
|
alert('Match nul !');
|
|
}
|
|
}
|
|
|
|
function resetBoard() {
|
|
board = Array.from({ length: 9 }, () => 0);
|
|
currentPlayer = 1;
|
|
running = true;
|
|
cells.forEach(cell => (cell.textContent = ''));
|
|
}
|
|
|
|
function toggleAi() {
|
|
aiEnabled = !aiEnabled;
|
|
gameMode = aiEnabled ? 'ai' : '1v1';
|
|
}
|
|
|
|
function minimax(tempBoard, maximizing) {
|
|
const winner = checkWinner(tempBoard);
|
|
|
|
if (winner !== 0) {
|
|
return { eval: winner === 1 ? 1 : -1, move: null };
|
|
} else if (!tempBoard.some(cell => cell === 0)) {
|
|
return { eval: 0, move: null };
|
|
}
|
|
|
|
let bestEval, bestMove;
|
|
|
|
if (maximizing) {
|
|
bestEval = -Infinity;
|
|
|
|
for (let i = 0; i < tempBoard.length; i++) {
|
|
if (tempBoard[i] === 0) {
|
|
const newBoard = [...tempBoard];
|
|
newBoard[i] = 1;
|
|
|
|
const eval = minimax(newBoard, false).eval;
|
|
if (eval > bestEval) {
|
|
bestEval = eval;
|
|
bestMove = i;
|
|
}
|
|
}
|
|
}
|
|
} 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return { eval: bestEval, move: bestMove };
|
|
}
|
|
|
|
cells.forEach(cell => cell.addEventListener('click', handleClick));
|
|
resetButton.addEventListener('click', resetBoard);
|
|
aiButton.addEventListener('click', toggleAi);
|