{}const=>[]async()letfn</>var
WebDevelopment

Creating a Tic-Tac-Toe game in JS, HTML, CSS

A detailed guide to creating a Tic-Tac-Toe game using HTML, CSS, and JavaScript. Ideal for beginner developers who want to learn how to program and create their first projects. Learn how to make the game interactive and stylish!

К

Kodik

Author

8 min read

Today we will guide you through the creation of the game "Tic-tac-toe" in JavaScript. This game is great for practicing programming and understanding how to interact with HTML, CSS and JavaScript! ⭐

If you are already a little familiar with programming and want to create something of your own, this article will help you understand the basics. And for the full source code, you can go to GitHub and see the project in action. Let's get started!

For the full source code and possibly additional improvements, check out our GitHub.

Step 1: Prepare the files 💻

To create a game, we need three files:

  1. HTML (index.html) - to create the page structure.

  2. CSS (style.css) - for page design.

  3. JavaScript (script.js) - for writing game logic.

HTML is responsible for the structure, CSS adds style and makes the interface pleasant, and JavaScript fills the game with logic and interactivity. First of all, let's take a look at the HTML file that creates the basis of our game.

HTML: Creating a structure

The HTML file creates the basis of the user interface. This is what the code looks like (part of the index.html file):

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Игра "Tic-tac-toe" | Coursme</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- окно выбора -->
  <div class="select-box">
    <header>Крестики-нолики</header>
    <div class="content">
      <div class="title">Выберите, кем вы хотите быть?</div>
      <div class="options">
        <button class="playerX">Игрок (X)</button>
        <button class="playerO">Игрок (O)</button>
      </div>
    </div>
  </div>

  <!-- игровое поле -->
  <div class="play-board">
    <div class="details">
      <div class="players">
        <span class="Xturn">Ход X</span>
        <span class="Oturn">Ход O</span>
        <div class="slider"></div>
      </div>
    </div>
    <div class="play-area">
      <section>
        <span class="box1"></span>
        <span class="box2"></span>
        <span class="box3"></span>
      </section>
      <section>
        <span class="box4"></span>
        <span class="box5"></span>
        <span class="box6"></span>
      </section>
      <section>
        <span class="box7"></span>
        <span class="box8"></span>
        <span class="box9"></span>
      </section>
    </div>
  </div>

  <!-- окно результата -->
  <div class="result-box">
    <div class="won-text"></div>
    <div class="btn"><button>Играть снова</button></div>
  </div>

  <script src="script.js"></script>
</body>
</html>

This HTML code creates three main sections:

  1. Player selection window - where the player chooses whether he will be X or O.

  2. Playing field - the main interface where players make their moves.

  3. Result window - displays the winner or a draw.

These three sections form the basis of our gameplay and make the interface clear and easy to use.

Step 2: Styling the game 🎨

The style.css file is responsible for the appearance of the game. Here are some key points:

  • The background of the game is painted in a pleasant purple color, which makes the interface bright and pleasant.

  • The player selection buttons have a smooth animation when hovering, which makes the interaction with the game more exciting.

  • The playing field is divided into cells, each of which is highlighted when hovered over, which helps players intuitively understand where they can make a move.

Code example from style.css:

body{
  background: #6563FF;
  color: #e0e0e0;
}
.play-area section span{
  display: block;
  height: 90px;
  width: 90px;
  margin: 2px;
  color: #fff;
  font-size: 40px;
  line-height: 80px;
  text-align: center;
  border-radius: 5px;
  background: #1e1e1e;
}

This style makes our game visually appealing and easy to use. The cells of the game field are neatly designed so that each move is clearly visible, and players can easily navigate the game field.

Now let's move on to the most interesting part - JavaScript!

Step 3: Game logic in JavaScript 🕹️

JavaScript is what makes our game interactive. Let's see how our script.js file works, starting with a simple player selection to determine the winner.

Game initialization and player selection

When the game loads, we immediately initialize some elements and add events for the player selection buttons. Here's how it's done:

// selection of all necessary elements
const selectBox = document.querySelector(".select-box"),
selectBtnX = selectBox.querySelector(".options .playerX"),
selectBtnO = selectBox.querySelector(".options .playerO"),
playBoard = document.querySelector(".play-board"),
players = document.querySelector(".players"),
allBox = document.querySelectorAll("section span"),
resultBox = document.querySelector(".result-box"),
wonText = resultBox.querySelector(".won-text"),
replayBtn = resultBox.querySelector("button");

window.onload = ()=>{ // after loading the window
    for (let i = 0; i < allBox.length; i++) { // add the onclick attribute for all available span
       allBox[i].setAttribute("onclick", "clickedBox(this)");
    }
}

Here we find all the elements necessary to control the game and add click events for each cell of the game field. This means that each cell becomes interactive and can respond to user actions.

Next comes the choice of the player:

selectBtnX.onclick = ()=>{
    selectBox.classList.add("hide"); // Hide the selection window
    playBoard.classList.add("show"); // Showing the game field
}

selectBtnO.onclick = ()=>{ 
    selectBox.classList.add("hide");
    playBoard.classList.add("show");
    players.setAttribute("class", "players active player"); // Setting the attribute for players
}

This code is responsible for showing or hiding different parts of the interface depending on which player was selected. When the selection is made, the selection window disappears and the game field appears on the screen.

Player and bot moves ➖➕

When a player selects a cell on the game board, we want an icon (X or O) to appear in that cell. Here's how we implement it:

let playerXIcon = "fas fa-times"; // FontAwesome cross icon class name
let playerOIcon = "far fa-circle"; // FontAwesome circle icon class name
let playerSign = "X"; // global variable, since we use it in several functions
let runBot = true; // global boolean variable to stop the bot when someone wins or draws

function clickedBox(element){
    if(players.classList.contains("player")){
        playerSign = "O"; // If the player chose O
        element.innerHTML = `<i class="${playerOIcon}"></i>`;
        players.classList.remove("active");
    }else{
        element.innerHTML = `<i class="${playerXIcon}"></i>`;
        players.classList.add("active");
    }
    element.setAttribute("id", playerSign); // Set the id attribute in the span/cell with the selected player sign
    selectWinner(); // Checking if there is a winner
    element.style.pointerEvents = "none"; // The cell can no longer be selected
    playBoard.style.pointerEvents = "none"; // Block the game field until the bot makes a move
    let randomTimeDelay = ((Math.random() * 1000) + 200).toFixed(); // Generating a random delay time
    setTimeout(()=>{
        bot(runBot); // Calling the bot function
    }, randomTimeDelay);
}

Here the player selects a cell, and it becomes unavailable for re-selection. Then the move is switched to the bot with a small delay to create the effect of a real game. Thus, the game becomes dynamic and interesting.

Bot function 🤖

The bot function automatically selects the next available cell. The bot makes a move after the player, and its actions also create the impression of interacting with a real opponent:

function bot(){
    let array = []; // create an empty array...we will store the indices of unselected cells
    if(runBot){ // if runBot true
        playerSign = "O"; // we change playerSign to O if the player chooses X
        for (let i = 0; i < allBox.length; i++) {
            if(allBox[i].childElementCount == 0){ // if the cell does not contain child elements
                array.push(i); // insert the index of unselected cells into the array
            }
        }
        let randomBox = array[Math.floor(Math.random() * array.length)]; // choose a random cell
        if(array.length > 0){
            if(players.classList.contains("player")){ 
                playerSign = "X"; // If the player chooses O, then the bot will be X
                allBox[randomBox].innerHTML = `<i class="${playerXIcon}"></i>`;
                allBox[randomBox].setAttribute("id", playerSign);
                players.classList.add("active");
            }else{
                allBox[randomBox].innerHTML = `<i class="${playerOIcon}"></i>`;
                players.classList.remove("active");
                allBox[randomBox].setAttribute("id", playerSign);
            }
            selectWinner(); // Checking if there is a winner
        }
        allBox[randomBox].style.pointerEvents = "none"; // The cell can no longer be selected
        playBoard.style.pointerEvents = "auto"; // Allow the player to click on the cell again
        playerSign = "X"; // Change of move back to the player
    }
}

The bot() function adds realism to the game, as the bot makes the choice automatically, creating the impression of a live opponent. The bot selects a random available cell, and this adds an element of surprise to the game.

Determining the winner 🏆

After each move, you need to check if there is a winner. To do this, use the selectWinner function:

function selectWinner(){
    if(checkIdSign(1,2,3,playerSign) || checkIdSign(4,5,6, playerSign) || checkIdSign(7,8,9, playerSign) || checkIdSign(1,4,7, playerSign) || checkIdSign(2,5,8, playerSign) || checkIdSign(3,6,9, playerSign) || checkIdSign(1,5,9, playerSign) || checkIdSign(3,5,7, playerSign)){
        runBot = false; // Stop the bot if someone wins
        setTimeout(()=>{ // Show result after 700 ms
            resultBox.classList.add("show");
            playBoard.classList.remove("show");
        }, 700);
        wonText.innerHTML = `Player <p>${playerSign}</p> won the game!`;
    }else{
        if(getIdVal(1) != "" && getIdVal(2) != "" && getIdVal(3) != "" && getIdVal(4) != "" && getIdVal(5) != "" && getIdVal(6) != "" && getIdVal(7) != "" && getIdVal(8) != "" && getIdVal(9) != ""){
            runBot = false; // Stop the bot if there is a draw
            setTimeout(()=>{ // Show result after 700 ms
                resultBox.classList.add("show");
                playBoard.classList.remove("show");
            }, 700);
            wonText.textContent = "The match ended in a draw!";
        }
    }
}

The selectWinner() function checks all possible winning combinations and determines if there is a winner. If all the cells are filled and no one has won, the game ends in a draw. This makes the game complete and logically completes each round.

Conclusion 🚀

Congratulations! Now you know how to create a simple Tic-Tac-Toe game using HTML, CSS, and JavaScript. We went through every step to create a pleasant user interface, add styles, and create game logic. Now you understand how the interactions between HTML, CSS, and JavaScript work, and how they can work together to create a full-fledged web application.

You can use this project as a basis for creating more complex games or even expand the functionality of this game. For example, add a win counter, improve the graphics, or make the game multiplayer. The possibilities are endless, and it all depends on your imagination and creativity!

For the full source code and possibly additional improvements, check out our GitHub.

If you have any questions, don't hesitate to ask. Good luck in programming, and may your projects always be as interesting and exciting! 👊🌟

🎯Stop procrastinating

Liked the article?
Time to practice!

In Kodik, you don't just read — you write code immediately. Theory + practice = real skills.

Instant practice
🧠AI explains code
🏆Certificate

No registration • No card