Implement minimax on expert mode to be unbeatable
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TIC TAC TOE</title>
<link rel="stylesheet" href="tictactoe.css">
</head>
<body>
<audio id="humanTurnSound" src="game.wav"></audio>
<audio id="aiTurnSound" src="game.wav"></audio>
<div style="justify-self: center;">
<h1>DIRECTION:</h1>
<p style="color: white; font-size: 50px; margin-bottom: 10px; text-align: center;">First to get 5 points win</p>
<div style="
">
<p style="color: white;font-size: 40px;margin-top: 25px;text-align: center;margin-bottom: .5px;">Score:</p>
<div style="display: flex;justify-content: center;align-items: center;">
<p style="color: white;font-size: 45px;margin-right: 10px;">X: <span id="scoreX">0</span></p>
<p style="color: white;font-size: 45px;">O: <span id="scoreO">0</span></p>
</div>
</div>
<div style="
text-align: center;
margin-top: 15px;
">
<select id="category">
<option value="Easy">Easy</option>
<option value="Difficult">Difficult</option>
<option value="Expert">Expert</option>
</select>
<div style="margin-top: 10px;">
<select id="players">
<option value="AIvsHuman">AI vs Human</option>
<option value="HumanvsHuman">Human vs Human</option>
</select>
</div>
</div>
</div>
<div class="container" style="">
<div id="game-container">
<div id="board" class="board">
</div>
</div>
<button id="reset-button" onclick="resetGame()" style="
color: white;
margin-top: 25px;
font-weight: 900;
background: linear-gradient(to right, #EBC1EE, #A277C6, #605399); /* Add more colors here */
animation: glow 2s infinite;
border-radius: 2px;
width: 150px;
height: 50px;
">Reset Game</button>
</div>
<div id="popup-container" class="popup-container">
<div class="popup-content">
<p id="popup-message"></p>
<button onclick="closePopup()">OK</button>
</div>
</div>
<footer style="position: absolute; left: 350px; bottom: -50px;">
<div style="text-align: center; background-color: rgba(71, 71, 71, 0.7); color: rgb(255, 255, 255); padding: 10px; border-radius: 10px;">
<h1 style="font-size: 34px;">Members</h1>
<p style="font-size: 30px; margin-bottom: 30px;">• Allyssa Gallo • Mary Joy Reano • Beverly Bernardino • Edward Cristobal • John Mark Oliveros</p>
</div>
</footer>
<script>
const humanTurnSound = document.getElementById('humanTurnSound');
const aiTurnSound = document.getElementById('aiTurnSound');
const rows = 5;
const columns = 6;
let currentPlayer = 'X';
let gameBoard = Array.from({ length: rows }, () => Array(columns).fill(''));
let scoreX = 0;
let scoreO = 0;
function createGameBoard() {
const boardElement = document.getElementById('board');
for (let i = 0; i < rows; i++) {
for (let j = 0; j < columns; j++) {
const cell = document.createElement('div');
cell.classList.add('cell');
cell.setAttribute('data-row', i);
cell.setAttribute('data-col', j);
cell.addEventListener('click', handleCellClick);
boardElement.appendChild(cell);
}
}
}
function showPopup(message) {
const popupContainer = document.getElementById('popup-container');
const popupMessage = document.getElementById('popup-message');
popupMessage.textContent = message;
popupContainer.style.display = 'flex';
}
function closePopup() {
const popupContainer = document.getElementById('popup-container');
popupContainer.style.display = 'none';
}
function handleCellClick(event) {
const clickedCell = event.target;
const row = Number(clickedCell.getAttribute('data-row'));
const col = Number(clickedCell.getAttribute('data-col'));
if (gameBoard[row][col] === '') {
gameBoard[row][col] = currentPlayer;
clickedCell.textContent = currentPlayer;
if (checkForWinner(row, col)) {
setTimeout(() => {
showPopup(${currentPlayer} wins!);
updateScores(currentPlayer);
resetGame();
}, 100);
} else {
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
if (document.getElementById('players').value === 'AIvsHuman' && currentPlayer === 'O') {
aiTurnSound.play();
makeAIMove();
} else {
humanTurnSound.play();
}
}
}
}
function checkForWinner(row, col) {
let countHorizontal = 0;
for (let i = 0; i < columns; i++) {
if (gameBoard[row] === currentPlayer) {
countHorizontal++;
if (countHorizontal >= 6) {
return true;
}
} else {
countHorizontal = 0;
}
}
let countVertical = 0;
for (let i = 0; i < rows; i++) {
if (gameBoard[col] === currentPlayer) {
countVertical++;
if (countVertical >= 5) {
return true;
}
} else {
countVertical = 0;
}
}
let countDiagonal1 = 0;
for (let i = -Math.min(row, col); i < Math.min(rows - row, columns - col); i++) {
if (gameBoard[row + i][col + i] === currentPlayer) {
countDiagonal1++;
if (countDiagonal1 >= 5) {
return true;
}
} else {
countDiagonal1 = 0;
}
}
if ((row === 1 && col === 0) || (row === 2 && col === 1) ||
(row === 3 && col === 2) || (row === 4 && col === 3)) {
let countDiagonal2 = 0;
for (let i = -Math.min(row, col); i < Math.min(rows - row, columns - col); i++) {
if (gameBoard[row + i][col + i] === currentPlayer) {
countDiagonal2++;
if (countDiagonal2 >= 4) {
return true;
}
} else {
countDiagonal2 = 0;
}
}
}
if ((row === 0 && col === 2) || (row === 1 && col === 3) ||
(row === 2 && col === 4) || (row === 3 && col === 5)) {
let countDiagonal3 = 0;
for (let i = -Math.min(row, col); i < Math.min(rows - row, columns - col); i++) {
if (gameBoard[row + i][col + i] === currentPlayer) {
countDiagonal3++;
if (countDiagonal3 >= 4) {
return true;
}
} else {
countDiagonal3 = 0;
}
}
}
if ((row === 0 && col === 3) || (row === 1 && col === 4) ||
(row === 2 && col === 5)) {
let countDiagonal4 = 0;
for (let i = -Math.min(row, col); i < Math.min(rows - row, columns - col); i++) {
if (gameBoard[row + i][col + i] === currentPlayer) {
countDiagonal4++;
if (countDiagonal4 >= 3) {
return true;
}
} else {
countDiagonal4 = 0;
}
}
}
if ((row === 0 && col === 4) || (row === 1 && col === 5)) {
let countDiagonal5 = 0;
for (let i = -Math.min(row, col); i < Math.min(rows - row, columns - col); i++) {
if (gameBoard[row + i][col + i] === currentPlayer) {
countDiagonal5++;
if (countDiagonal5 >= 2) {
return true;
}
} else {
countDiagonal5 = 0;
}
}
}
if ((row === 3 && col === 0) || (row === 4 && col === 1)) {
let countDiagonal6 = 0;
for (let i = -Math.min(row, col); i < Math.min(rows - row, columns - col); i++) {
if (gameBoard[row + i][col + i] === currentPlayer) {
countDiagonal6++;
if (countDiagonal6 >= 2) {
return true;
}
} else {
countDiagonal6 = 0;
}
}
}
if ((row === 2 && col === 0) || (row === 3 && col === 1) || (row === 4 && col === 2)) {
let countDiagonal7 = 0;
for (let i = -Math.min(row, col); i < Math.min(rows - row, columns - col); i++) {
if (gameBoard[row + i][col + i] === currentPlayer) {
countDiagonal7++;
if (countDiagonal7 >= 3) {
return true;
}
} else {
countDiagonal7 = 0;
}
}
}
let countDiagonal8 = 0;
for (let i = -Math.min(row, columns - col - 1); i < Math.min(rows - row, col + 1); i++) {
if (gameBoard[row + i][col - i] === currentPlayer) {
countDiagonal8++;
if (countDiagonal8 >= 5) {
return true;
}
} else {
countDiagonal8 = 0;
}
}
if ((row === 0 && col === 1) || (row === 1 && col === 0)) {
let countDiagonal9 = 0;
for (let i = -Math.min(row, columns - col - 1); i < Math.min(rows - row, col + 1); i++) {
if (gameBoard[row + i][col - i] === currentPlayer) {
countDiagonal9++;
if (countDiagonal9 >= 2) {
return true;
}
} else {
countDiagonal9 = 0;
}
}
}
if ((row === 0 && col === 2) || (row === 1 && col === 1) || (row === 2 && col === 0)) {
let countDiagonal10 = 0;
for (let i = -Math.min(row, columns - col - 1); i < Math.min(rows - row, col + 1); i++) {
if (gameBoard[row + i][col - i] === currentPlayer) {
countDiagonal10++;
if (countDiagonal10 >= 3) {
return true;
}
} else {
countDiagonal10 = 0;
}
}
}
if ((row === 0 && col === 3) || (row === 1 && col === 2) || (row === 2 && col === 1) || (row === 3 && col === 0)) {
let countDiagonal11 = 0;
for (let i = -Math.min(row, columns - col - 1); i < Math.min(rows - row, col + 1); i++) {
if (gameBoard[row + i][col - i] === currentPlayer) {
countDiagonal11++;
if (countDiagonal11 >= 4) {
return true;
}
} else {
countDiagonal11 = 0;
}
}
}
if ((row === 1 && col === 5) || (row === 2 && col === 4) || (row === 3 && col === 3) || (row === 4 && col === 2)) {
let countDiagonal12 = 0;
for (let i = -Math.min(row, columns - col - 1); i < Math.min(rows - row, col + 1); i++) {
if (gameBoard[row + i][col - i] === currentPlayer) {
countDiagonal12++;
if (countDiagonal12 >= 4) {
return true;
}
} else {
countDiagonal12 = 0;
}
}
}
if ((row === 2 && col === 5) || (row === 3 && col === 4) || (row === 4 && col === 3)) {
let countDiagonal13 = 0;
for (let i = -Math.min(row, columns - col - 1); i < Math.min(rows - row, col + 1); i++) {
if (gameBoard[row + i][col - i] === currentPlayer) {
countDiagonal13++;
if (countDiagonal13 >= 3) {
return true;
}
} else {
countDiagonal13 = 0;
}
}
}
if ((row === 3 && col === 5) || (row === 4 && col === 4)) {
let countDiagonal14 = 0;
for (let i = -Math.min(row, columns - col - 1); i < Math.min(rows - row, col + 1); i++) {
if (gameBoard[row + i][col - i] === currentPlayer) {
countDiagonal14++;
if (countDiagonal14 >= 2) {
return true;
}
} else {
countDiagonal14 = 0;
}
}
}
let isDraw = true;
for (let i = 0; i < rows; i++) {
for (let j = 0; j < columns; j++) {
if (gameBoard[j] === '') {
isDraw = false;
break;
}
}
if (!isDraw) {
break;
}
}
if (isDraw) {
showPopup('It\'s a draw!');
resetGame();
return false;
}
return false;
}
function makeAIMove() {
aiTurnSound.play();
let emptyCells = [];
for (let i = 0; i < rows; i++) {
for (let j = 0; j < columns; j++) {
if (gameBoard[j] === '') {
emptyCells.push({ row: i, col: j });
}
}
}
if (emptyCells.length > 0) {
if (document.getElementById('category').value === 'Difficult') {
// Difficult level strategy: Take the center or an edge
const centerAndEdges = emptyCells.filter(cell => (cell.row === 2 && cell.col === 2) || (cell.row % 2 === 0 && cell.col % 2 === 0));
const randomIndex = Math.floor(Math.random() * centerAndEdges.length);
const AIMove = centerAndEdges[randomIndex];
makeMoveAndUpdateDisplay(AIMove);
} else if (document.getElementById('category').value === 'Expert') {
// Expert level strategy: Prioritize winning moves and blocking opponent's winning moves
let winningMoveFound = false;
// Check for winning moves for the AI
for (let i = 0; i < emptyCells.length; i++) {
const testMove = emptyCells;
gameBoard[testMove.row][testMove.col] = 'O';
if (checkForWinner(testMove.row, testMove.col)) {
// Win the game if possible
makeMoveAndUpdateDisplay(testMove);
updateScores('O');
showPopup('O wins!');
resetGame();
return;
}
gameBoard[testMove.row][testMove.col] = '';
}
// Check for blocking opponent's winning moves
for (let i = 0; i < emptyCells.length; i++) {
const testMove = emptyCells;
gameBoard[testMove.row][testMove.col] = 'X';
if (checkForWinner(testMove.row, testMove.col)) {
// Block the opponent's winning move
makeMoveAndUpdateDisplay(testMove);
currentPlayer = 'X';
winningMoveFound = true;
break;
}
gameBoard[testMove.row][testMove.col] = '';
}
// If no winning moves or blocking moves, make a random move
if (!winningMoveFound) {
const randomIndex = Math.floor(Math.random() * emptyCells.length);
const AIMove = emptyCells[randomIndex];
makeMoveAndUpdateDisplay(AIMove);
}
} else {
// Basic level strategy: Make a random move
const randomIndex = Math.floor(Math.random() * emptyCells.length);
const AIMove = emptyCells[randomIndex];
makeMoveAndUpdateDisplay(AIMove);
}
}
}
function makeMoveAndUpdateDisplay(move) {
gameBoard[move.row][move.col] = 'O';
const AICell = document.querySelector(.cell[data-row="${move.row}"][data-col="${move.col}"]);
AICell.textContent = 'O';
setTimeout(() => {
if (checkForWinner(move.row, move.col)) {
updateScores('O');
showPopup('O wins!');
resetGame();
} else {
currentPlayer = 'X';
}
}, 100);
}
function updateScores(winner) {
if (winner === 'X') {
scoreX++;
document.getElementById('scoreX').textContent = scoreX;
if (scoreX === 5) {
showPopup('Player X wins the game!');
resetScoresAndGame();
}
} else if (winner === 'O') {
scoreO++;
document.getElementById('scoreO').textContent = scoreO;
if (scoreO === 5) {
showPopup('Player O wins the game!');
resetScoresAndGame();
}
}
}
function resetScoresAndGame() {
scoreX = 0;
scoreO = 0;
document.getElementById('scoreX').textContent = scoreX;
document.getElementById('scoreO').textContent = scoreO;
resetGame();
}
function resetGame() {
gameBoard = Array.from({ length: rows }, () => Array(columns).fill(''));
const cells = document.querySelectorAll('.cell');
cells.forEach(cell => {
cell.textContent = '';
});
currentPlayer = 'X';
}
createGameBoard();
</script>
</body>
</html>[/CODE]