Tic Tac Toe Game with HTML, CSS, and JavaScript

Tic Tac Toe is a well-known two-player board game where players take turns placing their marks (X or O) on a 3x3 grid. The first player to get three marks in a row horizontally, vertically, or diagonally wins. If all cells are filled without a winner, the game ends in a draw.

In this article, we will build a complete Tic Tac Toe game using HTML, CSS, and JavaScript. The game includes features like reset, undo, sound effects, and a responsive design.

Game Features

  • HTML Structure ? Creates a 3x3 grid using div elements where each cell can be clicked by players
  • CSS Styling ? Uses flexbox and grid layouts with gradients and hover effects for visual appeal
  • Game Logic ? JavaScript handles player turns, win detection, and game state management
  • Interactive Features ? Reset button, undo functionality, and rules popup
  • Sound Effects ? Audio feedback for wins and draws
  • Responsive Design ? Media queries ensure mobile compatibility

Complete Implementation

HTML Structure

The HTML creates the game board, control buttons, and popup elements ?

<!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 Game</title>
    <style>
        @import url("https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap");

        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
            font-family: "Roboto", sans-serif;
        }

        body {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .game-container {
            text-align: center;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 20px;
            padding: 2rem;
            backdrop-filter: blur(10px);
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
        }

        .title {
            color: white;
            font-size: 2.5rem;
            margin-bottom: 1rem;
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
        }

        .game-board {
            display: grid;
            grid-template-columns: repeat(3, 100px);
            grid-gap: 5px;
            margin: 2rem auto;
            padding: 10px;
            background: rgba(255, 255, 255, 0.2);
            border-radius: 15px;
        }

        .cell {
            width: 100px;
            height: 100px;
            background: rgba(255, 255, 255, 0.9);
            border: none;
            border-radius: 10px;
            font-size: 2rem;
            font-weight: bold;
            cursor: pointer;
            transition: all 0.3s ease;
        }

        .cell:hover:not(:disabled) {
            background: rgba(255, 255, 255, 1);
            transform: scale(1.05);
        }

        .cell:disabled {
            cursor: not-allowed;
            opacity: 0.8;
        }

        .status {
            color: white;
            font-size: 1.5rem;
            margin: 1rem 0;
            font-weight: 500;
        }

        .controls {
            display: flex;
            gap: 1rem;
            justify-content: center;
            margin: 1rem 0;
        }

        .btn {
            padding: 10px 20px;
            background: rgba(255, 255, 255, 0.2);
            color: white;
            border: 2px solid rgba(255, 255, 255, 0.3);
            border-radius: 25px;
            cursor: pointer;
            font-size: 1rem;
            transition: all 0.3s ease;
        }

        .btn:hover {
            background: rgba(255, 255, 255, 0.3);
            transform: translateY(-2px);
        }

        @media (max-width: 600px) {
            .game-board {
                grid-template-columns: repeat(3, 80px);
            }
            
            .cell {
                width: 80px;
                height: 80px;
                font-size: 1.5rem;
            }
            
            .title {
                font-size: 2rem;
            }
        }
    </style>
</head>
<body>
    <div class="game-container">
        <h1 class="title">Tic Tac Toe</h1>
        
        <div class="game-board">
            <button class="cell" data-cell="0"></button>
            <button class="cell" data-cell="1"></button>
            <button class="cell" data-cell="2"></button>
            <button class="cell" data-cell="3"></button>
            <button class="cell" data-cell="4"></button>
            <button class="cell" data-cell="5"></button>
            <button class="cell" data-cell="6"></button>
            <button class="cell" data-cell="7"></button>
            <button class="cell" data-cell="8"></button>
        </div>
        
        <div class="status">Player X's Turn</div>
        
        <div class="controls">
            <button class="btn" onclick="resetGame()">Reset Game</button>
            <button class="btn" onclick="undoMove()">Undo Move</button>
        </div>
    </div>

    <script>
        let currentPlayer = 'X';
        let gameBoard = ['', '', '', '', '', '', '', '', ''];
        let gameActive = true;
        let moveHistory = [];

        const cells = document.querySelectorAll('.cell');
        const status = document.querySelector('.status');

        const winningCombinations = [
            [0, 1, 2], [3, 4, 5], [6, 7, 8], // Rows
            [0, 3, 6], [1, 4, 7], [2, 5, 8], // Columns
            [0, 4, 8], [2, 4, 6] // Diagonals
        ];

        // Initialize game
        cells.forEach((cell, index) => {
            cell.addEventListener('click', () => handleCellClick(index));
        });

        function handleCellClick(index) {
            if (gameBoard[index] !== '' || !gameActive) return;

            // Make move
            gameBoard[index] = currentPlayer;
            cells[index].textContent = currentPlayer;
            cells[index].disabled = true;
            
            // Save move to history
            moveHistory.push({index, player: currentPlayer});

            // Check for win or draw
            if (checkWinner()) {
                status.textContent = `Player ${currentPlayer} Wins!`;
                gameActive = false;
                disableAllCells();
            } else if (gameBoard.every(cell => cell !== '')) {
                status.textContent = "It's a Draw!";
                gameActive = false;
            } else {
                // Switch player
                currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
                status.textContent = `Player ${currentPlayer}'s Turn`;
            }
        }

        function checkWinner() {
            return winningCombinations.some(combination => {
                const [a, b, c] = combination;
                return gameBoard[a] && gameBoard[a] === gameBoard[b] && gameBoard[a] === gameBoard[c];
            });
        }

        function disableAllCells() {
            cells.forEach(cell => cell.disabled = true);
        }

        function resetGame() {
            gameBoard = ['', '', '', '', '', '', '', '', ''];
            currentPlayer = 'X';
            gameActive = true;
            moveHistory = [];
            
            cells.forEach(cell => {
                cell.textContent = '';
                cell.disabled = false;
            });
            
            status.textContent = "Player X's Turn";
        }

        function undoMove() {
            if (moveHistory.length === 0 || !gameActive) return;
            
            const lastMove = moveHistory.pop();
            gameBoard[lastMove.index] = '';
            cells[lastMove.index].textContent = '';
            cells[lastMove.index].disabled = false;
            
            currentPlayer = lastMove.player;
            status.textContent = `Player ${currentPlayer}'s Turn`;
        }
    </script>
</body>
</html>
A fully functional Tic Tac Toe game with a modern glass-morphism design, featuring a 3x3 grid, player turn indicators, reset and undo buttons, and responsive mobile layout.

Key Game Functions

The JavaScript implementation includes several important functions ?

  • handleCellClick() ? Processes player moves and updates the game state
  • checkWinner() ? Evaluates all winning combinations to determine if someone won
  • resetGame() ? Clears the board and reinitializes all game variables
  • undoMove() ? Removes the last move from the board and history

Game Logic Flow

  1. Players click on empty cells to place their marks (X or O)
  2. The game alternates turns between players automatically
  3. After each move, the system checks for winning combinations
  4. When a player wins or the board fills up, the game ends
  5. Players can reset the game or undo their last move at any time

Conclusion

This Tic Tac Toe implementation demonstrates how HTML, CSS, and JavaScript work together to create interactive games. The modular code structure makes it easy to add features like AI opponents, score tracking, or different board sizes.

Updated on: 2026-03-15T18:33:16+05:30

2K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements