Welcome to Coding Torque. In this blog, we are going to create a Tic Tac Toe Game using HTML, CSS and JavaScript. You should create this project if you are an intermediate-level javascript developer.
Before we start, here are some more JavaScript projects for you to practice:
1. Filter Cards using JavaScript
2. Typing Effect using JavaScript
3. Email Validator using JavaScript
4. Tip Calculator using JavaScript
5. QR Code Generator using JavaScript
I would recommend you don't just copy and paste the code, just look at the code and type by understanding it.
Let's go step by step:
Step 1: HTML Code
Starter Template
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSS -->
<link rel="stylesheet" href="style.css">
<title>Tic Tac Toe Game using JavaSript using JavaScript with Source Code - @code.scientist x @codingtorque
</title>
</head>
<body>
<!-- Further code here -->
<script src="script.js"></script>
</body>
</html>
Paste the below code in your <body> tag
<table id="scoreboard" align="center">
<tr>
<td> Player 1 </td>
<td width="30"> </td>
<td> Player 2 </td>
</tr>
<tr>
<td class="score" id="player1">
0
</td>
<td> </td>
<td class="score" id="player2">
0
</td>
</tr>
</table>
<div id="placeholder"></div>
<button onclick="restart()">
Reset
</button>
<select onchange="restart(this.value)">
<option value="2">
2 X 2
</option>
<option value="3" selected="">
3 X 3
</option>
<option value="4">
4 X 4
</option>
<option value="5">
5 X 5
</option>
<option value="6">
6 X 6
</option>
</select>
Output Till Now
Step 2: CSS Code
Create a file style.css and paste the code below.
body {
font: normal 16px comic sans ms;
text-align: center;
}
#tic-tac-toe {
cell-spacing: 0px;
border-spacing: 0px;
border-collapse: separate;
margin: 30px auto;
}
#tic-tac-toe td {
border: 2px solid #000;
height: 100px;
width: 100px;
text-align: center;
font: bold 60px comic sans ms;
}
#tic-tac-toe tr:first-child td {
border-top: none;
}
#tic-tac-toe tr:last-child td {
border-bottom: none;
}
#tic-tac-toe tr td:first-child {
border-left: none;
}
#tic-tac-toe tr td:last-child {
border-right: none;
}
#tic-tac-toe td.X {
color: #ed676b;
}
#tic-tac-toe td.O {
color: #23916b;
}
#scoreboard .score {
text-align: center;
font-size: 30px;
}
#scoreboard .score#player1 {
color: #ed676b;
}
#scoreboard .score#player2 {
color: #23916b;
}
Output Till Now
Step 3: JavaScript Code
Create a file script.js and paste the code below.
function TicTacToe(placeholder, grid_size, callback) {
// Save the placeholder element
this.placeholder = placeholder;
// Paint the placeholder with board
this.paint(grid_size);
// Save the callback
this.callback = callback;
// Save player scores
this.scores = {
X: 0,
O: 0
};
this.marks = {
X: "X", // Player 1 mark
O: "O", // Player 2 mark
count: 0 // Number of moves made by player
};
return this;
}
TicTacToe.prototype.paint = function(grid_size) {
var self = this;
// Get number of columns, considering board as N x N board (3 x 3)
self.grid_size = grid_size;
var html = '<table id="tic-tac-toe" align="center">';
for(var i = 0; i < grid_size; i++) {
html += '<tr>';
for(var j = 0; j < grid_size; j++) {
html+= '<td></td>';
}
html += '</tr>';
}
html += '</table>';
self.placeholder.innerHTML = html;
// Find all columns from the board
self.columns = self.placeholder.getElementsByTagName("td");
// Go through all the columns and add click event
for(i = 0; i < this.columns.length; i++) {
self.columns[i].addEventListener("click", markHandler);
}
// on click mark the column "<td>"
function markHandler(e) {
self.mark(e.target);
}
};
TicTacToe.prototype.mark = function(column) {
// Stop if column is not empty
if(column.innerHTML) {
return;
}
// Count the move
this.marks.count++;
// Get the mark based on the count
var current_mark = this.marks.count % 2 === 1 ? this.marks.X : this.marks.O;
// Fill the column with mark
column.innerHTML = current_mark;
column.classList.add(current_mark);
// Check if this player (X or O) won
if(this.didWin(current_mark)) {
// Increment the player score
if(this.marks.count % 2 === 1) {
this.scores.X++;
} else {
this.scores.O++;
}
// Send current mark and scores
this.callback(current_mark, this.scores);
} else if(this.marks.count === this.columns.length) {
// Send result as draw
this.callback("draw");
}
};
// Board:
// _____________
// | 0 | 1 | 2 |
// |---|---|---|
// | 3 | 4 | 5 |
// |---|---|---|
// | 6 | 7 | 8 |
// -------------
//
// We need to go through all columns like
//
// 012, 345, 678 - Horizontal
// 036, 147, 258 - Vertical
// 048, 246 - Diagonal
//
// If mark is present in all columns of any combinations then user won
//
// Instead of going through each combination manually we can make use of loops,
// So that it can be used for any grids like 7 X 7
//
TicTacToe.prototype.didWin = function(mark) {
// Take count of columns
var grid_size = this.grid_size;
// Declare variables to count the presence of the mark
var horizontal_count,
vertical_count,
right_to_left_count = 0,
left_to_right_count = 0;
// Loop 1
for(var i = 0; i < grid_size; i++) {
// Empty the count
horizontal_count = vertical_count = 0;
// Loop 2
for(var j = 0; j < grid_size; j++) {
// i * grid_size + j ===> "0,1,2", "3,4,5", "6,7,8"
if(this.columns[i * grid_size + j].innerHTML == mark) {
horizontal_count++;
}
// j * grid_size + i ===> "0,3,6", "1,4,7", "2,5,8"
if(this.columns[j * grid_size + i].innerHTML == mark) {
vertical_count++;
}
}
// If horizontal or vertical combination is found the return true
if(horizontal_count == grid_size || vertical_count == grid_size) {
return true;
}
// i * grid_size + i ===> "0,4,8"
if(this.columns[i * grid_size + i].innerHTML == mark) {
right_to_left_count++;
}
// (grid_size - 1) * (i+1) ===> "2,4,6"
if(this.columns[(grid_size - 1) * (i+1)].innerHTML == mark) {
left_to_right_count++;
}
} // End of loop
// If mark is present diagnolly
if(right_to_left_count == grid_size || left_to_right_count == grid_size) {
return true;
}
return false;
};
TicTacToe.prototype.empty = function() {
// Go through all columns and empty them
for(var i = 0; i < this.columns.length; i++) {
this.columns[i].innerHTML = '';
this.columns[i].classList.remove(this.marks.X);
this.columns[i].classList.remove(this.marks.O);
}
// Reset the count
this.marks.count = 0;
};
TicTacToe.prototype.reset = function() {
this.empty();
this.scores = {
X: 0,
O: 0
};
};
var placeholder = document.getElementById("placeholder");
var tictactoe = new TicTacToe(placeholder, 3, onResult);
function onResult(result, scores) {
if(result == 'draw') {
alert("It's a draw !");
} else {
alert(result + " has won");
updateScores(scores.X, scores.O);
}
tictactoe.empty();
}
function updateScores(X, O) {
document.querySelector("#scoreboard #player1").innerHTML = X;
document.querySelector("#scoreboard #player2").innerHTML = O;
}
function restart(grid_size) {
tictactoe.reset();
updateScores(0, 0);
if(grid_size) {
tictactoe.paint(grid_size);
}
}
Code Credits: @captain-mad
Written by: Coding Torque | Piyush PatilIf you want me to code any project or post any specific post, feel free to DM me at IG @code.scientist or @codingtorque
If you have any doubts or any project ideas feel free to Contact Us
Hope you find this post helpful💖
Follow us on Instagram for more projects like this👨💻