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 JavaScript Games you might like to create:
1.Ā Snake Game using JavaScript
2.Ā 2D Bouncing Ball Game using JavaScript
3.Ā Rock Paper Scissor Game using JavaScript
4.Ā Tic Tac Toe Game using JavaScript
5. Whack a Mole Game using JavaScript
I would recommend you don’t just copy and paste the code, just look at the code and type by understanding it.
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
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
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); } }
Written by: Piyush Patil
Code Credits:Ā @captain-mad
If you have any doubts or any project ideas feel free to Contact Us
Hope you find this post helpfulš