So yea. We making Tic-Tac-Toe.
Why? Why not?
What is Tic-Tac-Toe?
Tic-Tac-Toe is a game where you have a 3x3 grid and you have to get 3 of your symbols in a row to win. The symbols can be X or O.
How do you play Tic-Tac-Toe?
You play Tic-Tac-Toe by placing your symbol in an empty space in the grid. The first player to get 3 of their symbols in a row wins. (Horizontal, Vertical, or Diagonal).
So we are going to make a Tic-Tac-Toe game with HTML, CSS, and Javascript.
First, we are going to make the grid.
<div class="grid">
<div id="b0">O</div>
<div id="b1">X</div>
<div id="b2">X</div>
<div id="b3">X</div>
<div id="b4">O</div>
<div id="b5">X</div>
<div id="b6">O</div>
<div id="b7">O</div>
<div id="b8">X</div>
</div>
Let’s put some random values for now.
Now we are going to make the grid look like a grid.
.grid {
display: grid;
gap: 1vw;
grid-template-columns: repeat(3, 1fr);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
div>div {
padding: 10px;
background-color: rgb(129, 247, 145);
text-align: center;
width: 5vw;
min-width: 100px;
border-radius: 10%;
border-style: solid;
border-color: rgb(129, 247, 145);
box-shadow: -2px 3px 0 black;
font-family: Arial, Helvetica, sans-serif;
font-size: 5rem;
}
Now let’s make each box in the grid actually hoverable and clickable.
div>div:hover {
background-color: rgb(255, 255, 255);
color: rgb(0, 0, 0);
border-color: rgb(0, 0, 0);
cursor: pointer;
}
document.addEventListener("click", function (element) {
if (
element.target.id.startsWith("b") &&
!element.target.disabled
) {
playerMove(element.target);
// This is a function that we will make later.
}
});
Now we are going to make the playerMove function.
function playerMove(element) {
if (playerOne) {
element.innerText = "O";
playerOne = false;
} else {
element.innerText = "X";
playerOne = true;
}
}
This function will basically make the div that is clicked on have an X or O in it depending on whose turn it is.
To actually determine whose turn it is we are going to make a variable called playerOne.
let playerOne = true;
If playerOne is true then it is player one’s turn and if it is false then it is player two’s turn.
At the moment we can click anywhere on the grid and it will put a X or O in the div that we clicked on. We don’t want that. We want it so that you can only click on a div that is empty.
To do this we can make a list of 9 False values and when a div is clicked on we can change the value of the list to True.
let allowed = [false, false, false, false, false, false, false, false, false];
To associate each div with a value in the list we can make a list of the id’s of each div.
var list = ["b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"];
So now our playerMove function will look like this.
function playerMove(element) {
if (allowed[list.indexOf(element.id)] == false) {
if (playerOne) {
element.innerText = "O";
allowed[list.indexOf(element.id)] = true;
playerOne = false;
} else {
indicator.innerText = "Its O's Turn";
element.innerText = "X";
allowed[list.indexOf(element.id)] = true;
playerOne = true;
}
} else {
// Do nothing as the div is already filled.
}
}
Now we are going to make a function that will check if someone has won.
There are 19,683 different ways the 3x3 grid can be filled
But for someone to win there are only 8 different ways.
So let’s write our checkWin function.
function checkWin() {
var win = false;
var winner = "";
// We check for Horizontal Wins
if (
document.getElementById(list[0]).innerText ==
document.getElementById(list[1]).innerText &&
document.getElementById(list[1]).innerText ==
document.getElementById(list[2]).innerText &&
document.getElementById(list[0]).innerText != ""
) {
win = true;
winner = document.getElementById(list[0]).innerText;
} else if (
document.getElementById(list[3]).innerText ==
document.getElementById(list[4]).innerText &&
document.getElementById(list[4]).innerText ==
document.getElementById(list[5]).innerText &&
document.getElementById(list[3]).innerText != ""
) {
win = true;
winner = document.getElementById(list[3]).innerText;
} else if (
document.getElementById(list[6]).innerText ==
document.getElementById(list[7]).innerText &&
document.getElementById(list[7]).innerText ==
document.getElementById(list[8]).innerText &&
document.getElementById(list[6]).innerText != ""
) {
win = true;
winner = document.getElementById(list[6]).innerText;
}
// We check for Vertical Wins
else if (
document.getElementById(list[0]).innerText ==
document.getElementById(list[3]).innerText &&
document.getElementById(list[3]).innerText ==
document.getElementById(list[6]).innerText &&
document.getElementById(list[0]).innerText != ""
) {
win = true;
winner = document.getElementById(list[0]).innerText;
} else if (
document.getElementById(list[1]).innerText ==
document.getElementById(list[4]).innerText &&
document.getElementById(list[4]).innerText ==
document.getElementById(list[7]).innerText &&
document.getElementById(list[1]).innerText != ""
) {
win = true;
winner = document.getElementById(list[1]).innerText;
} else if (
document.getElementById(list[2]).innerText ==
document.getElementById(list[5]).innerText &&
document.getElementById(list[5]).innerText ==
document.getElementById(list[8]).innerText &&
document.getElementById(list[2]).innerText != ""
) {
win = true;
winner = document.getElementById(list[2]).innerText;
}
// We check for Diagonal Wins
else if (
document.getElementById(list[0]).innerText ==
document.getElementById(list[4]).innerText &&
document.getElementById(list[4]).innerText ==
document.getElementById(list[8]).innerText &&
document.getElementById(list[0]).innerText != ""
) {
win = true;
winner = document.getElementById(list[0]).innerText;
} else if (
document.getElementById(list[2]).innerText ==
document.getElementById(list[4]).innerText &&
document.getElementById(list[4]).innerText ==
document.getElementById(list[6]).innerText &&
document.getElementById(list[2]).innerText != ""
) {
win = true;
winner = document.getElementById(list[2]).innerText;
}
// Check if the whole grid is filled by checking if all of allowed is true
else if (allowed.every((val, i, arr) => val === true)) {
win = true;
winner = "Nobody";
}
return win, winner;
}
So basically what this function does is it checks if any of the divs are filled with the same value and if they are then it returns true and the winner checks for horizontal wins, vertical wins, and diagonal wins.
if Nobody wins then it returns true and the winner is Nobody so it means that it’s a draw.
Let’s add one more thing to our Tic Tac Toe game. We are gonna make an indicator that tells us whose turn it is and if someone wins.
<div id="indicator"></div>
var indicator = document.getElementById("indicator");
function playerMove(element) {
if (allowed[list.indexOf(element.id)] == false) {
if (playerOne) {
indicator.innerText = "Its X's Turn";
element.innerText = "O";
allowed[list.indexOf(element.id)] = true;
playerOne = false;
checkWin();
} else {
indicator.innerText = "Its O's Turn";
element.innerText = "X";
allowed[list.indexOf(element.id)] = true;
playerOne = true;
checkWin();
}
} else {
indicator.innerText = "This spot is already taken";
}
}
Let’s make our final function which will end the game.
function finishGame(winner) {
if (winner == "Nobody") {
indicator.innerText = "Nobody won! How sad...";
} else indicator.innerText = "The winner is " + winner + "!";
}
Now we just need to call this function in our checkWin function.
function checkWin() {
...
// Check if its filled by seeing if all of allowed is true
else if (allowed.every((val, i, arr) => val === true)) {
win = true;
winner = "Nobody";
}
if (win && winner != "") {
finishGame(winner);
}
return win, winner;
}
Now we are done with our Tic Tac Toe game!
You can find the final code at https://github.com/Arisamiga/Tic-Tac-Toe and you can play the game at https://arisamiga.github.io/Tic-Tac-Toe/
This was a very nice project to make and I actually got to work on it with my friend so it was even more fun. It was interesting as I got to work with Grids and Arrays and also got to learn about the different ways and logic to win in Tic Tac Toe.
Hope you enjoyed this project and Thanks so much for reading :D