Tic Tac Toe Game with Minimax Algorithm

Answered using OpenAI o1 mini by OpenAI o1

Question:

Generate code for a tic tac toe game. use html, css and javascript. use the minmax algorithm. include a restart button functionality. include feedback messages, example: "Players turn" or "AI is thinking...". lastly, combine all files in the html file

Answer:

Sure! Below is a complete implementation of a Tic Tac Toe game using HTML, CSS, and JavaScript, all combined into a single HTML file. The game uses the Minimax algorithm for the AI's moves and includes a restart button and feedback messages.

<!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>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            background-color: #f0f0f0;
        }
        h1 {
            margin-bottom: 20px;
        }
        #board {
            display: grid;
            grid-template-columns: repeat(3, 100px);
            grid-template-rows: repeat(3, 100px);
            gap: 5px;
        }
        .cell {
            width: 100px;
            height: 100px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 2em;
            background-color: white;
            border: 2px solid #333;
            cursor: pointer;
        }
        .cell:hover {
            background-color: #e0e0e0;
        }
        #message {
            margin: 20px;
            font-size: 1.2em;
        }
        button {
            padding: 10px 20px;
            font-size: 1em;
            cursor: pointer;
        }
    </style>
</head>
<body>

<h1>Tic Tac Toe</h1>
<div id="message">Players turn</div>
<div id="board"></div>
<button id="restart">Restart</button>

<script>
    const boardElement = document.getElementById('board');
    const messageElement = document.getElementById('message');
    const restartButton = document.getElementById('restart');

    let board = ['', '', '', '', '', '', '', '', ''];
    let currentPlayer = 'X';
    let gameActive = true;

    const winningConditions = [
        [0, 1, 2],
        [3, 4, 5],
        [6, 7, 8],
        [0, 3, 6],
        [1, 4, 7],
        [2, 5, 8],
        [0, 4, 8],
        [2, 4, 6]
    ];

    function createBoard() {
        boardElement.innerHTML = '';
        board.forEach((cell, index) => {
            const cellElement = document.createElement('div');
            cellElement.classList.add('cell');
            cellElement.setAttribute('data-index', index);
            cellElement.innerText = cell;
            cellElement.addEventListener('click', handleCellClick);
            boardElement.appendChild(cellElement);
        });
    }

    function handleCellClick(event) {
        const index = event.target.getAttribute('data-index');
        if (board[index] !== '' || !gameActive) return;

        board[index] = currentPlayer;
        checkResult();
        if (gameActive) {
            messageElement.innerText = "AI is thinking...";
            setTimeout(() => {
                aiMove();
            }, 500);
        }
        createBoard();
    }

    function checkResult() {
        let roundWon = false;
        for (let i = 0; i < winningConditions.length; i++) {
            const [a, b, c] = winningConditions[i];
            if (board[a] === '' || board[b] === '' || board[c] === '') continue;
            if (board[a] === board[b] && board[a] === board[c]) {
                roundWon = true;
                break;
            }
        }

        if (roundWon) {
            messageElement.innerText = `${currentPlayer} has won!`;
            gameActive = false;
            return;
        }

        if (!board.includes('')) {
            messageElement.innerText = "It's a draw!";
            gameActive = false;
            return;
        }

        currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
        messageElement.innerText = `${currentPlayer === 'X' ? "Players turn" : "AI is thinking..."}`;
    }

    function aiMove() {
        const bestMove = minimax(board, 'O').index;
        board[bestMove] = 'O';
        checkResult();
        createBoard();
    }

    function minimax(newBoard, player) {
        const availableSpots = newBoard.reduce((acc, curr, index) => {
            if (curr === '') acc.push(index);
            return acc;
        }, []);

        if (checkWin(newBoard, 'X')) {
            return { score: -10 };
        } else if (checkWin(newBoard, 'O')) {
            return { score: 10 };
        } else if (availableSpots.length === 0) {
            return { score: 0 };
        }

        const moves = [];
        for (let i = 0; i < availableSpots.length; i++) {
            const move = {};
            move.index = availableSpots[i];
            newBoard[availableSpots[i]] = player;

            if (player === 'O') {
                const result = minimax(newBoard, 'X');
                move.score = result.score;
            } else {
                const result = minimax(newBoard, 'O');
                move.score = result.score;
            }

            newBoard[availableSpots[i]] = '';
            moves.push(move);
        }

        let bestMove;
        if (player === 'O') {
            let bestScore = -Infinity;
            for (let i = 0; i < moves.length; i++) {
                if (moves[i].score > bestScore) {
                    bestScore = moves[i].score;
                    bestMove = i;
                }
            }
        } else {
            let bestScore = Infinity;
            for (let i = 0; i < moves.length; i++) {
                if (moves[i].score < bestScore) {
                    bestScore = moves[i].score;
                    bestMove = i;
                }
            }
        }

        return moves[bestMove];
    }

    function checkWin(board, player) {
        return winningConditions.some(condition => {
            return condition.every(index => {
                return board[index] === player;
            });
        });
    }

    restartButton.addEventListener('click', () => {
        board = ['', '', '', '', '', '', '', '', ''];
        currentPlayer = 'X';
        gameActive = true;
        messageElement.innerText = "Players turn";
        createBoard();
    });

    createBoard();
</script>

</body>
</html>

Explanation:

  • HTML Structure: The HTML contains a title, a message area, a board for the game, and a restart button.
  • CSS Styles: Basic styles are applied to center the content, style the board, and provide hover effects.
  • JavaScript Logic:
    • The game state is managed using an array board.
    • The createBoard function generates the game board dynamically.
    • The handleCellClick function processes player moves and triggers the AI's turn.
    • The checkResult function checks for a win or draw after each move.
    • The aiMove function uses the Minimax algorithm to determine the best move for the AI.
    • The minimax function implements the Minimax algorithm recursively.
    • The restart button resets the game state.

You can copy and paste this code into an HTML file and open it in a web browser to play the game!