Tic Tac Toe Game using HTML, CSS and JavaScript - Coding Torque

Tic Tac Toe Game using HTML, CSS and JavaScript - Coding Torque

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"> &nbsp; </td>
        <td> Player 2 </td>
    </tr>
    <tr>
        <td class="score" id="player1">
            0
        </td>
        <td> &nbsp; </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

Tic Tac Toe Game using HTML, CSS and JavaScript - Coding Torque

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 Patil

If 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👨‍💻 

Post a Comment

Previous Post Next Post