Create a Simple Tic-Tac-Toe Web App with HTML, CSS, and JavaScript

SUDHIR PATELSUDHIR PATEL
5 min read

Now, it's exciting to share that I am building my first project while learning HTML, CSS, and JS. It might be an easy project for experienced developers, but it's quite challenging for me as a beginner. Just kidding! I'll share the code and a view of the app so you can see how simple it is.

The HTML code of the app:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tic-Tac-Toy</title>
    <link rel="stylesheet" href="tic.css">
</head>
<body>
    <header>
        <h2>Tic-Tac-Toy - Shaktiman</h2>
    </header>
    <main>
        <div class="msg-winner hide">
            <p id="msg">Winner</p>
        </div>

        <div id="container">
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
            <div class="box"></div>
        </div>
    </main>
    <footer>
        <button id="reset">Reset Game</button>
        <button id="new">New Game</button>
    </footer>
    <script src="tic.js"></script>
</body>
</html>
  • The document starts with the <!DOCTYPE html> declaration, which tells the browser that this is an HTML5 document.

  • The <html> tag begins the HTML document, and it specifies the language as English with lang="en".

  • Inside the <head> section, the character encoding is set to UTF-8, and the viewport is configured for responsive design.

  • The title of the page is set to "Tic-Tac-Toy".

  • A link to an external CSS file named "tic.css" is included to style the page.

  • The <body> contains the main content of the page.

  • A header section includes a heading with the text "Tic-Tac-Toy - Shaktiman".

  • The main section has a hidden message area for displaying the winner, with the text "Winner".

  • A container with nine div elements represents the tic-tac-toe grid, each with the class "box".

  • The footer includes two buttons: one to reset the game and another to start a new game.

  • Finally, a script tag links to an external JavaScript file named "tic.js" to add functionality to the page.

The CSS code for the app


body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    height: 100vh;
    font-family: Arial, sans-serif;
    background-color: #f0f0f0;
    margin: 0;
}

header h2 {
    margin: 20px 0;
    background-color: #f0f0f0;
}

#container {
    display: grid;
    grid-template-columns: repeat(3, 100px);
    grid-template-rows: repeat(3, 100px);
    gap: 10px;
}

.box {
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: #fff;
    border: 2px solid #000;
    box-shadow: 2px 2px 5px rgba(180, 226, 16, 0.5);
    border-radius: 0.5rem;
    font-size: 50px;
}

button {
    width: 100%;
    height: 100%;
    background-color: transparent;
    border: none;
    font-size: 2em;
    cursor: pointer;
}

footer {
    margin-top: 20px;
}


footer {
    display: flex;
    justify-content: center;
    gap: 5px; 
    margin-top: 20px;
}

#reset {
    padding: 10px 10px;
    font-size: 1em;
    cursor: pointer;
    background-color: red;
    color: #fff;
    border-radius: 1rem;
}


#new {
    padding: 10px 10px;
    font-size: 1em;
    cursor: pointer;
    background-color: green;
    color: #fff;
    border-radius: 1rem;
}
#msg{
    text-align: center;
    color: #000;
    font-size: 20px;
    font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;


}

.hide{
    display: none;
}

The CSS styles define the layout and appearance of a webpage. The header has a margin and a light gray background. The main container uses a grid layout with three columns and rows, each 100px, and a 10px gap between items. Each box within the grid is centered, has a white background, a black border, a shadow, and rounded corners. The font size inside the boxes is large. Buttons cover their entire area, have no background or border, and change the cursor to a pointer. The footer is centered with a small gap between items. The reset and new buttons have padding, a specific font size, a colored background, white text, and rounded corners. The message is centered with black text in a specific font and size. The .hide class hides elements.

The JavaScript Code of the App

let boxes = document.querySelectorAll(".box");
let rstbtn = document.querySelector("#reset");
let newbtn = document.querySelector("#new");
let msgContainer = document.querySelector(".msg-winner");
let msg = document.querySelector("#msg");

let turn0 = true; // for O turn 
let gameActive = true; // Variable to track game status

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

boxes.forEach((box, index) => {
    box.addEventListener("click", () => {
        if (box.innerText === "" && gameActive) {
            if (turn0) {
                box.innerText = "O";
                turn0 = false;
            } else {
                box.innerText = "X";
                turn0 = true;
            }
            box.setAttribute("aria-disabled", "true");
            checkWinner();  
        }
    });
});

const disableBoxes = () => {
    boxes.forEach((box) => {
        box.setAttribute("aria-disabled", "true");
    });
};

const enableBoxes = () => {
    boxes.forEach((box) => {
        box.removeAttribute("aria-disabled");
        box.innerText = "";
    });
};

const showWinner = (winner) => {
   msg.innerText = `Congratulations, Winner is ${winner}`;
   msgContainer.classList.remove("hide");
   gameActive = false; // Deactivate the game
};

const checkWinner = () => {
    for (let pattern of winPatterns) {
        let pos1val = boxes[pattern[0]].innerText;
        let pos2val = boxes[pattern[1]].innerText;
        let pos3val = boxes[pattern[2]].innerText;

        if (pos1val !== "" && pos1val === pos2val && pos2val === pos3val) {
            console.log(`Winner: ${pos1val}`);
            showWinner(pos1val);
            return;
        }
    }
};

const resetGame = () => {
    enableBoxes();
    turn0 = true;
    gameActive = true; // Reactivate the game
    msgContainer.classList.add("hide");
};

const startNewGame = () => {
    resetGame();
    let start = prompt("Who starts first? Enter 'O' or 'X'");
    if (start === "X" || start === "x") {
        turn0 = false; // X's turn
    } else {
        turn0 = true; // O's turn
    }
};

rstbtn.addEventListener("click", resetGame);
newbtn.addEventListener("click", startNewGame);

This code manages a simple game. It includes functions to check for a winner, show the winner, reset the game, and start a new game. The checkWinner function looks for winning patterns and announces the winner. The resetGame function prepares the game for a new round by enabling the boxes and hiding messages. The startNewGame function resets the game and asks who will start first, either 'O' or 'X'. Buttons are set up to reset the game or start a new one when clicked.

What You Learn While Building This Project

Building this project teaches you how to manage game logic using JavaScript. You'll learn how to check for winning patterns and display the winner. You'll also understand how to reset the game for a new round and prompt players to choose who starts first. Additionally, you'll gain experience in setting up buttons to reset the game or start a new one with simple click events.

GitHub Link : https://github.com/sudhirskp/tic-tac-toe

The article discusses the creation of a simple Tic-Tac-Toe game using HTML, CSS, and JavaScript. It explains the setup of the game interface and styling, along with the JavaScript logic for managing game flow, checking for winning patterns, and handling user interactions. This project serves as a practical exercise for beginners to understand the basics of web development and game logic handling.

0
Subscribe to my newsletter

Read articles from SUDHIR PATEL directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

SUDHIR PATEL
SUDHIR PATEL