DEV Community

reyes2981
reyes2981

Posted on

what i learned last week: how to build tic tac toe using html, css and javascript

Good Morning! It's a snowy Sunday here in Chicago and today I'm going to build the game tic tac toe. In the process of building this program I will provide a high level overview of HTML, CSS and JavaScript.
tic tac toe

HTML

The first thing I'm going to do is create an index.html file. Remember, HTML is the standard markup language for creating Web pages. I like to think of it as the "skeleton" of a website.
html skeleton Next, I want to start writing code in the newly created index.html file. The boilerplate code for an index.html file should look something like this...

<!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">
    <title>Document</title>
</head>
<body>

</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Note, HTML (HyperText Markup Language) is the most basic building block of the Web. It defines the meaning and structure of web content.
element tree Next, utilizing <div>'s, I'm going to build the tic tac toe board. The <div> tag defines a division or a section in an HTML document. It's also used as a container for HTML elements - which is then styled with CSS or manipulated with JavaScript.

<!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">
    <title>Document</title>
</head>
<body>
    <!-- Tic Tac Toe Board -->
    <div id="board-container">
      <div data-index="1" class="box"></div>
      <div data-index="2" class="box"></div>
      <div data-index="3" class="box"></div>
      <div data-index="4" class="box"></div>
      <div data-index="5" class="box"></div>
      <div data-index="6" class="box"></div>
      <div data-index="7" class="box"></div>
      <div data-index="8" class="box"></div>
      <div data-index="9" class="box"></div>
    </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

I'm making good progress! So far, I've created an index.html file and added <div>'s that represent a tic tac toe board. Notice that I've created a div with an id of board-container. The HTML id attribute is used to specify a unique id for an HTML element. Nested inside of the #board-container div there are 9 separate, child, <div>'s that represent a cell in the tic tac toe board. Remember, an HTML document is like a big family tree, with parents, siblings, children, ancestors, and descendants. I'm about to dive into CSS and will need to somehow reference these newly created children elements so I'm adding a class of box to each individual <div>.

CSS

Next, I want to see this newly created grid so let's build and display it to the client side using CSS. If HTML is the skeleton of a website than CSS is the clothes that dress up a person.
CSS
Below, is a screenshot of my completed tic tac toe game - designed with CSS.
tictactoe1

#board-container {
  width: 300px;
  height: 300px;
  margin: 0 auto;
  background-color: #e9c46a;
  color: #fff;
  border: 6px solid #e9c46a;
  border-radius: 10px;
  display: grid;
  grid-template: repeat(3, 1fr) / repeat(3, 1fr);
  position: relative;
  top: 30%;
}
Enter fullscreen mode Exit fullscreen mode

Note, I'm able to style a div by referencing it's id attribute. The same thing can also be done with the class attribute.
css syntax

JavaScript

Below is part of the code used to build and store the logic of my program.

document.addEventListener("DOMContentLoaded", () => {
    console.log("DOM Content Loaded");
    //RETREIVE HTML ELEMENTS
    const boxes = document.querySelectorAll(".box");
    const strikethrough = document.getElementById("strikethrough");
    const gameOverArea = document.getElementById("game-over-area");
    const gameOverText = document.getElementById("game-over-text");
    const playAgain = document.getElementById("play-again");
    const playerxDiv = document.getElementById("player-X");
    const playeroDiv = document.getElementById("player-O");
    //CREATE PLAYERS, ARRAY THAT REPRESENTS BOARD AND WINNING COMBOS
    const playerX = "X";
    const playerO = "O";
    const boardArray = Array(boxes.length); //TRACKS STATE OF PROGRAM - CREATED AN ARRAY WHICH HAS 9 ITEMS(BOXES)
    const winningCombos = [
        //ROWS
        {  // KEY   VALUE
            combo: [0, 1, 2],
            strikeClass: "strike-row-1"
        },
        {
            combo: [3, 4, 5],
            strikeClass: "strike-row-2"
        },
        {
            combo: [6, 7, 8],
            strikeClass: "strike-row-3"
        },
        //COLUMNS
        {
            combo: [0, 3, 6],
            strikeClass: "strike-column-1"
        },
        {
            combo: [1, 4, 7],
            strikeClass: "strike-column-2"
        },
        {
            combo: [2, 5, 8],
            strikeClass: "strike-column-3"
        },
        //DIAGONALS
        {
            combo: [0, 4, 8],
            strikeClass: "strike-diagonal-1"
        },
        {
            combo: [2, 4, 6],
            strikeClass: "strike-diagonal-2"
        },
    ];
    let turn = playerX; //TRACKS WHO'S TURN IT IS

    playAgain.addEventListener("click", restartGame);

    //THE FILL() METHOD CHANGES ALL ELEMENTS IN AN ARRAY TO A STATIC VALUE, FROM A START INDEX (DEFAULT 0) TO 
    //AN END INDEX (DEFAULT ARRAY.LENGTH). IT RETURNS THE MODIFIED ARRAY
    boardArray.fill(null);

    playerxDiv.append(playerX);
    playeroDiv.append(playerO);


    boxState();
    //FUNCTION THAT ITERATATES OVER LIST OF BOXES AND ADDS AN EVENT LISTENER TO EACH INDIVIDUAL BOX
    function boxState() {
        boxes.forEach((box) => {
            box.addEventListener("click", boxClick); //FUNCTION WILL BE CALLED WHENEVER THE SPECIFIED EVENT IS DELIVERED TO THE TARGET
        })
    }

    function boxClick(e) {
        const box = e.target; //REFERENCE TO THE HTML ELEMENT CLICKED
        const boxNumber = box.dataset.index;//ACCESS DATA-INDEX ATTRIBUTE
        //IF GAMEOVER AREA CLASSLIST CONTAINNS "VISIBLE" THE FUNCTION WILL STOP EXECUTING
        if (gameOverArea.classList.contains("visible")) {
            return;
        }
        //CHECK IF SPECIFIC BOX IS EMPTY OR HAS AN "X" OR "O" IN IT
        if (box.innerText != "") {
            return;
        }
        if (turn === playerX) {
            box.innerText = playerX;
            boardArray[boxNumber - 1] = playerX; //ARRAYS ARE ZERO INDEXED SO I NEED TO SUBTRACT 1 FROM PLAYERS CHOICE FOR GAME TO BE ACCURATE
            turn = playerO;
            console.log(`It's ${playeroDiv.innerText}'s turn`);
        } else {
            box.innerText = playerO;
            boardArray[boxNumber - 1] = playerO;
            turn = playerX;
            console.log(`It's ${playerxDiv.innerText}'s turn`);
        }

        //FUNCTION IS CALLED ON EVERY SINGLE BOX CLICK - CHECKS IF THERE IS A WINNER
        checkWinner()
    }
Enter fullscreen mode Exit fullscreen mode

Deployed Program: https://clever-noether-f61a54.netlify.app/
Github: https://github.com/reyes2981/project1

Top comments (0)