3 min read
In this game project we will create a simple game with basic HTML, CSS and javascript. This game is fully functional but still there is room for improvement. Let's get started!
The HTML we need in our project will consist of 3 major parts. The title that we will use to show whose turn it is. The div to render our game board. Another title for our modal. Our modal will be invisible initially but we will make it visible when the game is over. In the modal we will have a button to simply reload the page.
The full code for the "index.html" file is here:
<!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>Document</title>
<script defer src="main.js"></script>
</head>
<body>
<h1 class="turn-title"></h1>
<div class="game-wrapper">
<div class="game-box 1"></div>
<div class="game-box 2"></div>
<div class="game-box 3"></div>
<div class="game-box 4"></div>
<div class="game-box 5"></div>
<div class="game-box 6"></div>
<div class="game-box 7"></div>
<div class="game-box 8"></div>
<div class="game-box 9"></div>
</div>
<div class="finished-modal">
<button class="modal-btn">RESTART</button>
<p class="modal-text"></p>
</div>
</body>
</html>
We will start with the basics. Create the "style.css" file. I like to add the following piece of code in all my projects:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: rgb(226, 237, 236);
}
All we did was to set some basic values for our project.
Now we can start styling our board. Our board will be a 3x3 grid that contains 9 boxes. Instead of working with borders I just gave my grid a darker background value and set a grid-gap value. Now we know where the boxes are. You can add this part of our CSS file right below the we just wrote:
.turn-title {
margin-bottom: 50px;
}
.game-wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 1vw;
background: rgb(0, 0, 0);
border: none;
}
.game-box {
width: 140px;
height: 140px;
font-size: 8rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: rgb(151, 218, 212);
}
I actually made this part responsive for mobile users but I deleted it to create a small challenge for you. You should go ahead and make it prettier. Maybe even create a cute animation. It's always a good idea to go one step further. It will make a much more confident developer.
The rest of our CSS will be for our modal and modal button to refresh the page. The modal will cover the page and will have the "display: fixed" value. This will keep it above all other content on our page. The content inside the modal will appear in the center (with minimal CSS really). As you can see here, the CSS I used here is also very simple:
.finished-modal {
width: 100%;
background: rgba(0, 0, 0, 0.5);
height: 100%;
color: white;
font-size: 2rem;
position: fixed;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
visibility: hidden;
}
.modal-btn {
background-color:rgb(100, 170, 166);
padding: 20px;
font-size: 2rem;
border-radius: 15px;
border: none;
color: white;
transition: 0.5s;
}
.modal-btn:hover {
background-color: rgb(9, 169, 156);
cursor: pointer;
}
This code can be added at the bottom of the style.css file to keep a somewhat consistent look.
Our javascript is the only (somewhat) complicated part of our game. First of all what we need is an array of values to render inside the boxes. These values later will be chosen by clicking on them to be replaced with the current user's mark. We will alternate the "current" value between "X" and "O".
We need to let the users know whose turn it is to play. We will select the empty h1 title and set the the text content of this title.
To render the values inside the grid (and into the boxes), I chose to use an array with the length of 9. It will be initialized with 9 empty strings. In our HTML you can see that in our classes we also numbered our boxes. This way when we click on them by using this class values we will be able to know their place in the array. This will allow us to replace the empty string value with the current value we have for the user (either X or O).
To Check if there is a winner after every click on our board I created 2 functions. For our horizontal and vertical checks we will use a simple for loop. I hardcoded the diagonal check but if you have a better way of creating this part, go for it. IT will be a good exercise.
If we find a winner in our functions described above, we need to of course handle it. We should set a message and show this message using our modal. We will show the modal by changing the display value of the modal to block (from hidden).
I tried to explain the code in comments as well. If there is anything you have trouble understanding, just play with the code for a while and I'm sure you will make sense of it. The full code can be found here:
const turn = document.querySelector('.turn-title');
const finishedModal = document.querySelector('.finished-modal');
const modalBtn = document.querySelector('.modal-btn');
const boxes = document.querySelectorAll('.game-box')
const gameArray = ["","","","","","","","",""];
let winner = undefined;
// We will start with X
let current = "X";
// Now set the text value of the title to show
// whose turn it is
turn.textContent = `${current}'s Turn`
// With this function I'm rendering the values inside my
// gameArray inside the boxes
const render = () => {
for(let i = 0; i < 9; i++){
boxes[i].textContent = gameArray[i]
}
}
render();
addEventListener('click', (e) => {
// If we click on restart button
if(e.target === modalBtn) {
window.location.reload(true);
return
}
// get the number of the box
const boxNum = parseInt(e.target.classList[1]) - 1;
// If that box is not empty
if(gameArray[boxNum] !== "") return
// If the box is empty
gameArray[boxNum] = current
// Check if there's a winner
horizontalVerticalCheck()
diagonalCheck();
// If all the empty strings are replaced in the array
if(gameArray.indexOf("") < 0) gameFinished(winner)
// Place the current mark
if(current === 'X') current = 'O';
else if(current === 'O') current = 'X';
turn.textContent = `${current}'s Turn`
// Run the render again to render the latest array
render();
});
const diagonalCheck = () => {
if(
gameArray[0] === gameArray[4] &&
gameArray[0] === gameArray[8] &&
gameArray[0] !== ""
){
console.log(current, "wins")
winner = current;
gameFinished(winner)
return;
}
else if(
gameArray[2] === gameArray[4] &&
gameArray[2] === gameArray[6] &&
gameArray[2] !== ""
) {
console.log(current, "wins")
winner = current;
gameFinished(winner)
return;
}
}
const horizontalVerticalCheck = () => {
// Checking for horizontal and vertical alignments
for(let i = 0; i < 3; i++){
// check for vertical alignment
if(
// example: arr[0] === arr[3] === arr[6]
gameArray[i] === gameArray[i+3] &&
gameArray[i] === gameArray[i+6] &&
gameArray[i] !== ""
){
console.log(current, "wins")
winner = current;
gameFinished(winner)
return;
}
// check for horizontal alignment
else if(
// example: arr[0] === arr[1] === arr[2]
gameArray[3*i] === gameArray[3*i+1] &&
gameArray[3*i] === gameArray[3*i+2] &&
gameArray[3*i] !== ""
) {
console.log(current, "wins")
winner = current;
gameFinished(winner)
return;
}
}
}
const gameFinished = (winner) => {
let text = undefined;
// If there's no winner when the game ends
if(winner === undefined) {
text = "There is no winner in this round!"
} else {
text = `Winner is ${winner}, congratulations!`
}
// If the text is defined above
if(text !== undefined) {
const modal = document.querySelector('.finished-modal');
const p = document.querySelector('.modal-text');
p.textContent = text;
modal.appendChild(p);
// Show the modal
modal.style.visibility = 'visible';
}
}
This game was very fun and fast to create. I'm sure you will also have fun creating yours. But you shouldn't just copy the code I created here. I suggest that you improve it.
Not all games need to be complex, this was an example for creating a simple yet fun game using some basic web development knowledge.
Ilker Akbiyik