DEV Community

Hussaini Ahmed
Hussaini Ahmed

Posted on • Updated on

How I built a Tic Tac Toe Game using vanilla Javascript.

Image description
Tic Tac Toe is a classic game that many of us have played at some point in our lives. The game uses a 3×3 grid. The goal of the game is to be the first player to place three symbols in a straight horizontal, vertical, or diagonal row. If you are a beginner in the field of web development, building a game like Tic Tac Toe is a good start to help build and develop your programming skills.

Prerequisite

To be able to develop a game like Tic Tac Toe, you will need a solid background knowledge in the following languages:

  • HTML
  • CSS
  • JavaScript

Building a Tic Tac Toe Game with HTML, CSS, and JavaScript


To start building a Tic Tac Toe Game, we will need to create three seperate files(HTML, CSS, and JavaScript respectively). You can go ahead and open your favourite code editor and proceed to create the files.

HTML Structure

Let's start by creating the HTML structure for our game. We will use a simple table to represent the game board. Each cell in the table will represent a position on the board. We will also create a
section to display the game score and a button to reset the game. Here is the code for our HTML structure:


<!DOCTYPE html> <html lang="en"> 
    <head> <meta charset="UTF-8"> 
    <meta http-equiv="X-UA-Compatible" content="IE=edge"> 
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
    <link rel="stylesheet" href="style.css"> 
    <title>Tic Tac Toe Game</title> 
</head> 
<body> 
    <div id="main"> 
        <table> 
            <caption>Tic Tac Toe Game</caption> 
            <tr> 
                <td id="0"></td> 
                <td id="1"></td> 
                <td id="2"></td> 
            </tr> 
            <tr> 
                <td id="3"></td> 
                <td id="4"></td> 
                <td id="5"></td> 
            </tr> 
            <tr> 
                <td id="6"></td> 
                <td id="7"></td> 
                <td id="8"></td> 
            </tr>
        </table>
        <div id="game-score"> 
            <h1 id="player"></h1> 
            <h3 id="text"></h3> 
        </div> 
        <button id="reset-btn">Reset Game</button> 
</div> <script src="script.js"></script> 
</body> 
</html>
Enter fullscreen mode Exit fullscreen mode

The code starts with the HTML5 doctype declaration and sets the language to English for the document. It then defines the head section of the document, which includes the meta tags for character set, compatibility mode, and viewport. The stylesheet for the game is also linked to the document.

The body section of the document contains a div element with an ID of "main" that wraps all the game elements, including a table with 3 rows and 3 columns to represent the Tic Tac Toe game board. Each cell of the table has a unique ID (0-8) to enable JavaScript code to access them easily.

The code also includes a div element with an ID of "game-score" to display the current game score, a heading element with an ID of "player" to display the current player's turn, a subheading element with an ID of "text" to display game-related messages, and a button element with an ID of "reset-btn" to reset the game when clicked.

Finally, the code includes a script tag with the source attribute "script.js," which will be used to write the JavaScript code for the Tic Tac Toe game.

Now that we've added the HTML structure, let's proceed to include the CSS styling.

CSS Styling

Next, we will add some CSS styling to our HTML elements. We will use CSS to create a simple and clean interface for our game. We will also use CSS to define the style of our table cells, game score section, and reset button. Here is the code for our CSS styling:

#main{
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
}

Enter fullscreen mode Exit fullscreen mode

The #main selector applies thedisplay: flex property to the main element and sets the flex-direction tocolumn, which aligns the game elements in a vertical column. justify-content and align-items center the elements both horizontally and vertically, and text-align centers the text within the main element.

table {
    display: block;
    border-collapse: collapse;
    margin: 20px auto;
}

Enter fullscreen mode Exit fullscreen mode

The table selector applies the display: block property and border-collapse: collapse, which removes the borders between cells on the table. It also sets the margin property to center the table horizontally.

caption{
    font-size: 32px;
    margin: 24px auto;
}

Enter fullscreen mode Exit fullscreen mode

The caption selector sets the font-size to 32px and adds margin to center the caption within the table.

td{
    border: 1px solid black;
    width: 80px;
    height: 80px;
    font-size: 48px;
    text-align: center;
    vertical-align: middle;
}


Enter fullscreen mode Exit fullscreen mode

The td selector sets the border property to 1px solid black, and sets the width and height properties to 80px. The font-size is set to 48px to increase the size of the symbols and text-align and vertical-align properties are set to center the content within each cell.

td:hover {
    background-color: #eee;
    cursor: pointer;
}

Enter fullscreen mode Exit fullscreen mode

The td:hover selector applies the background-color of #eee to the table cell when the mouse hovers over it, and the cursor property is set to pointer to provide visual feedback to the user.

button {
    display: block;
    margin: 20px auto;
    padding: 10px 20px;
    font-size: 16px;
    border-radius: 5px;
    border: none;
    background-color: #4CAF50;
    color: white;
}

Enter fullscreen mode Exit fullscreen mode

The button selector sets the display property to block and the margin property to center the button. It also sets the padding property,font-sizeproperty, and border-radius property to round the corners. The border property is set to none, and the background-color is set to #4CAF50, which is a shade of green, while the color is set to white.

button:hover {
    background-color: #3e8e41;
    cursor: pointer;
}

Enter fullscreen mode Exit fullscreen mode

The button:hover selector applies the background-color of #3e8e41 to the button when the mouse hovers over it and the cursor property is set to pointer.

#game-winner{
    display: none;
}
Enter fullscreen mode Exit fullscreen mode

The #game-winner selector applies the display: none property to the game-winner element to hide it by default, and it will be used to display the winner when the game ends.

JavaScript Functionality

Now, we will add JavaScript functionality to our game. We will use JavaScript to implement the game logic, handle user input, and update the game score. We will create functions to check for a winner

Declare variables


//Declare variables
let currentPlayer = 'X';
let gameEnded = false;
let gameMoves = ['', '', '', '', '', '', '', '', ''];
Enter fullscreen mode Exit fullscreen mode

At the beginning of the JavaScript code, there are three variables declared - currentPlayer, gameEnded, and gameMoves.

The currentPlayer variable keeps track of whose turn it is. It is initially set to 'X'.

The gameEnded variable is used to determine if the game has ended. It is initially set to false.

The gameMoves variable is an array that represents the state of the game. Each index in the array corresponds to a cell on the game board. The initial state of the gameMoves array is an empty string for each cell.

Get DOM

//Get DOM
const boxes = document.querySelectorAll('td');
const table = document.querySelector('table');
const gameScore = document.querySelector('#game-score');
let player = document.querySelector('#player');
let text =  document.querySelector('#text');
Enter fullscreen mode Exit fullscreen mode

the code uses the querySelectorAll() method to select all the table cells (td elements) in the game board. It also selects the table, the #game-score element, the #player elementand #text element.

Add event listener to table cells

//add event listener to table boxes
  boxes.forEach((box, index) =>{
      box.addEventListener('click', ()=>{
          if (!gameEnded && gameMoves[index] === '') {
              gameMoves[index] = currentPlayer;
              box.textContent = currentPlayer;
              //check for winner
              if (gameWin()) {
                  table.style.display = 'none';
                  gameScore.style.display = 'block';
                  player.textContent = currentPlayer;
                  text.textContent = 'WINNER';
                  gameEnded = true;
              }
              //check for tie
              else if (gameTie()) {
                  table.style.display = 'none';
                  gameScore.style.display = 'block';
                  player.textContent = 'XO';
                  text.textContent = 'DRAW';
                  gameEnded = true;
              } else{
                  currentPlayer = currentPlayer === 'X' ? '0' : 'X';
              }
          } 
      });
  });
Enter fullscreen mode Exit fullscreen mode

A forEach loop is used to add a click event listener to each table cell. When a table cell is clicked, the event listener triggers a function that checks if the game has ended, if the cell has already been clicked, and updates the gameMoves array accordingly.

Check for winner function

//Check for winner function
  const gameWin = ()=>{
      const winningCombos = [
      [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
    ];
    return winningCombos.some(combo=>{
      return combo.every(index=>{
          return gameMoves[index] === currentPlayer;
      })
    })
  }
Enter fullscreen mode Exit fullscreen mode

The gameWin() function checks if the current player has won the game. It does this by checking if any of the winning combinations (rows, columns, or diagonals) have all the same value (either 'X' or '0').

The function uses the some() method to iterate through each winning combination and the every() method to iterate through each index in the combination. If all the indexes in a combination have the same value as the current player, the function returns true, and the current player has won.

Check for tie function

//Check for tie function
  const gameTie = ()=>{
      return gameMoves.every(move => {
          return move !== '';
      });
  }
Enter fullscreen mode Exit fullscreen mode

The gameTie() function checks if the game is a tie. It does this by checking if all the cells on the game board have been clicked.

The function uses the every() method to iterate through each element in the gameMoves array. If every element is not an empty string, the function returns true, and the game is a tie.

Update game state

If the current player has won the game, the table is hidden, and the game-score div is displayed. The div displays the current player's move and the text 'WINNER'. The gameEnded variable is set to true.

If the game is a tie, the table is hidden, and the game-score div is displayed. The div displays 'XO' and the text 'DRAW'. The gameEnded variable is set to true.

If the game is not over, the currentPlayer variable is updated to the other player.

Reset game function

//Reset game function
  const resetGame = ()=>{
    table.style.display = 'block';
    gameScore.style.display = 'none';
    currentPlayer = 'X';
    gameEnded = false;
    gameMoves = ['', '', '', '', '', '', '', '', ''];
    boxes.forEach(box => {
      box.textContent = '';
    });
}
Enter fullscreen mode Exit fullscreen mode
//Event listener for reset button
const resetButton = document.getElementById('reset-btn');
resetButton.addEventListener('click', resetGame);
Enter fullscreen mode Exit fullscreen mode

The resetGame() function is called when the reset button is clicked. It sets the game back to its initial state by resetting the gameMoves array, the currentPlayer variable, and the gameEnded variable. It also clears the text in each cell on the game board and hides the game-score div.

Overall, this JavaScript code works by using a combination of event listeners, functions, and variables to keep track of the game state and update the game board as players make their moves. It also checks for a winner or tie and updates the game state accordingly. Finally, it provides a way to reset the game and start over.
This is the complete javascript code.

//Declare variables
let currentPlayer = 'X';
let gameEnded = false;
let gameMoves = ['', '', '', '', '', '', '', '', ''];
//Get DOM
  const boxes = document.querySelectorAll('td');
  const table = document.querySelector('table');
  const gameScore = document.querySelector('#game-score');
  let player = document.querySelector('#player');
  let text =  document.querySelector('#text');
  //add event listener to table boxes
  boxes.forEach((box, index) =>{
      box.addEventListener('click', ()=>{
          if (!gameEnded && gameMoves[index] === '') {
              gameMoves[index] = currentPlayer;
              box.textContent = currentPlayer;
              //check for winner
              if (gameWin()) {
                  table.style.display = 'none';
                  gameScore.style.display = 'block';
                  player.textContent = currentPlayer;
                  text.textContent = 'WINNER';
                  gameEnded = true;
              }
              //check for tie
              else if (gameTie()) {
                  table.style.display = 'none';
                  gameScore.style.display = 'block';
                  player.textContent = 'XO';
                  text.textContent = 'DRAW';
                  gameEnded = true;
              } else{
                  currentPlayer = currentPlayer === 'X' ? '0' : 'X';
              }
          } 
      });
  });
  //Check for winner function
  const gameWin = ()=>{
      const winningCombos = [
      [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
    ];
    return winningCombos.some(combo=>{
      return combo.every(index=>{
          return gameMoves[index] === currentPlayer;
      })
    })
  }
  //Check for tie function
  const gameTie = ()=>{
      return gameMoves.every(move => {
          return move !== '';
      });
  }
  //Reset game function
  const resetGame = ()=>{
    table.style.display = 'block';
    gameScore.style.display = 'none';
    currentPlayer = 'X';
    gameEnded = false;
    gameMoves = ['', '', '', '', '', '', '', '', ''];
    boxes.forEach(box => {
      box.textContent = '';
    });
}

  //Event listener for reset button
  const resetButton = document.getElementById('reset-btn');
  resetButton.addEventListener('click', resetGame);
Enter fullscreen mode Exit fullscreen mode

Congratulations, you've just learnt how to create a Tic Tac Toe game using HTML, CSS and Javascript. By now you should be able to build your own version, feel free to modify and use the code to build yours. Ensure you do not copy paste the code but rather write it from scratch and play around with the code to see if you can add new functionalities or edit existing ones to suit your needs. This will not only help you understand the code but also ensure you grow your coding skills faster.

Conclusively, i want to thank you for finding time to read this article, i sincerely hope you enjoyed it, however if you come across any bugs whilst trying out the code, please do not hesitate to let me know.

My name is Hussaini Ahmed, I am a front end developer. I also write about front end languages, frameworks and latest technologies. I’d loved to hear your thought on this article. Feel free to drop a comment below or reach out to me via:

Upwork
Github
WhatsApp
Twitter
LinkedIn

Top comments (0)