DEV Community

Cover image for Tic Tac Toe Game with HTML, CSS & JavaScript — Live Demo + Source Code
Siddhesh Mithbavkar
Siddhesh Mithbavkar

Posted on

Tic Tac Toe Game with HTML, CSS & JavaScript — Live Demo + Source Code

💡 Why This Project Matters

Every developer has built Tic-Tac-Toe app, but I built this version not just as a game, but as a practical exercise in frontend polish and asset management. It demonstrates that you can achieve a professional feel—complete with smooth UI transitions and audio feedback—using nothing but pure JavaScript and core web technologies.

This project goes beyond the basics to tackle real-world challenges like cross-origin audio loading and effective DOM state synchronization.

tic tac toe game


🧠 The Core Logic: Managing the Game State

At the heart of the application is a centralized state array and a single function, handleResultValidation, which drives the entire game flow. I built the logic to ensure the visual elements are always a direct reflection of this single source of truth.

1. The State Array

The game state is managed by a simple array mapping the 9 cells:

let boardState = ["", "", "", "", "", "", "", "", ""];
let currentPlayer = "X";
let gameActive = true;
Enter fullscreen mode Exit fullscreen mode

2. The Winning Check (The Engine)

The critical part of the code is iterating through the predefined winning conditions to check for three matching symbols. I built this function to immediately apply the visual highlight before ending the game.

const winningConditions = [/* ... all 8 win combos ... */];

const handleResultValidation = () => {
    let roundWon = false;
    for (let i = 0; i < winningConditions.length; i++) {
        const [aIndex, bIndex, cIndex] = winningConditions[i];

        if (boardState[aIndex] === boardState[bIndex] && boardState[aIndex] === boardState[cIndex] && boardState[aIndex] !== '') {
            roundWon = true;

            // Crucial UI Update: Highlight the winning cells
            cells[aIndex].classList.add('win'); 
            cells[bIndex].classList.add('win');
            cells[cIndex].classList.add('win'); 

            winSound.play().catch(e => console.warn(e)); // Play the victory sound
            break;
        }
    }
    // ... rest of win/draw/player change logic ...
};
Enter fullscreen mode Exit fullscreen mode

🔊 Sound Design: Overcoming CORS and Playback Issues

Adding audio for clicks and wins required tackling a persistent frontend headache: Cross-Origin Resource Sharing (CORS). I built the solution around using a CORS-compliant CDN (like Cloudinary) to ensure the audio files load correctly on the CodePen domain.

The Audio Playback Handler

The key to preventing the click sound from getting cut off during rapid clicks is resetting the playback time to zero before calling play(). I built the handleCellPlayed function to guarantee instant, responsive audio feedback.

const handleCellPlayed = (clickedCell, clickedCellIndex) => {
    // Update state and visual DOM
    boardState[clickedCellIndex] = currentPlayer;
    clickedCell.innerHTML = currentPlayer;
    clickedCell.classList.add(currentPlayer.toLowerCase());

    // Essential for responsive playback:
    clickSound.currentTime = 0; 
    clickSound.play().catch(e => console.warn(e)); // Use .catch() for error handling

    handleResultValidation();
};
Enter fullscreen mode Exit fullscreen mode

🎨 CSS Polish: Highlighting Key States

The visual appeal relies on clear differentiation and smooth transitions. I built the CSS to make the most important states immediately obvious:

/* Styling for the Win Highlight */
.cell.win {
    background-color: #27ae60; /* Green highlight for winning cells */
    color: white;
    box-shadow: 0 0 15px #2ecc71;
    transform: scale(1.05);
}

/* Smooth transition for hover and interaction */
.cell {
    transition: background-color 0.3s, transform 0.1s;
}

/* Responsive button feedback */
#reset-button:active {
    box-shadow: 0 2px #773b93;
    transform: translateY(2px);
}
Enter fullscreen mode Exit fullscreen mode

tic tac toe game winning ui


🔗 Live Demo and Source Code

This project showcases fundamental JavaScript optimization and DOM manipulation skills. Feel free to explore the full source code and see these principles in action!

Top comments (0)