
Today, we will learn how to develop a tic-tac-toe game in JavaScript. We will be using HTML for the front end and CSS for designing. Tic Tac Toe is a very famous game that we all play during our childhood. Rules are also very simple. Two players play at a time, they are given 9 boxes and they need to choose 1 box at a time. The player of chooses 3 straight boxes or 3 diagonal boxes wins the game.
Let’s check what we are going to develop.
Output of Tic-Tac-Toe game in JavaScript:

Code for the Tic-Tac-Toe game in JavaScript:
<html>
<link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet'>
<div class="gameArea gameAreaHide">
<div class="title">
Tic-Tac-Toe
</div>
<div class="resultField">
<div>
<span id="playerDisplay" class="playerDisplayOne">
Player <span class="displayXO">X</span>
</span>
<span class="playerOne"></span>
<span class="resultPlayerOne">0</span>
</div>
<div>
<span id="playerDisplay" class="playerDisplayTwo">
Player <span class="displayXO">O</span>
</span>
<span class="playerTwo"></span>
<span class="resultPlayerTwo">0</span>
</div>
</div>
<div class="messageField">
<div class="messageFieldInner"></div>
</div>
<div class="playField">
<button id="one" class="firstRow firstColumn diagonalDown"></button>
<button id="two" class="firstRow secondColumn"></button>
<button id="three" class="firstRow thirdColumn diagonalUp"></button>
<button id="four" class="secondRow firstColumn"></button>
<button id="five" class="secondRow secondColumn diagonalDown diagonalUp"></button>
<button id="six" class="secondRow thirdColumn"></button>
<button id="seven" class="thirdRow firstColumn diagonalUp"></button>
<button id="eight" class="thirdRow secondColumn"></button>
<button id="nine" class="thirdRow thirdColumn diagonalDown"></button>
</div>
<div class="winnerWindow">
<span class="winner">WINNER</span>
<span class="winnerName">Name Of Winner</span>
<button class="playAgain">Play Again</button>
<button class="resetGame">Reset Game</button>
</div>
</div>
<!-- player names -->
<div class="playerNames">
<div class="title">
Tic-Tac-Toe
</div>
<form action="/tic-tac-toe">
<div>
<label for="playerX">Player1 Name:</label>
<input type="text" name="" id="playerX" autofocus>
</div>
<div>
<label for="playerO">Player2 Name:</label>
<input type="text" name="" id="playerO">
</div>
<button>
Let's Start The Game!!
</button>
</form>
</div>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: 'Montserrat';
font-weight: 500;
}
*::selection {
user-select: none;
}
body {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background-color: rgb(207, 224, 232);
cursor: default;
}
button {
cursor: pointer;
background-color: rgb(207, 224, 232);
font-weight: 600;
border: none;
box-shadow: 2px 3px 8px rgba(0, 0, 0, 0.61);
}
.spanXO {
font-family: 'Montserrat';
font-size: 30px;
font-weight: 400;
}
.title {
width: 100%;
height: 10%;
letter-spacing: 3px;
text-align: center;
padding-top: 5px;
font-size: 36px;
color: white
}
.playerNames {
width: 400px;
height: 500px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
background-color: rgb(0,0,0);
border: 2px solid rgb(255,255,255);
}
.playerNamesHide {
display: none;
}
form {
width: 100%;
height: 90%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
label {
display: block;
font-size: 25px;
letter-spacing: 1px;
color: white;
}
form div {
width: 60%;
height: 120px;
}
input {
font-size: 25px;
color: white;
padding: 1px 5px;
letter-spacing: 3px;
width: 100%;
background-color: transparent;
border: none;
border-bottom: 2px solid rgb(255, 255, 255);
outline: none;
}
form button {
width: 55%;
font-size: 20px;
letter-spacing: 1px;
padding: 7px 20px;
}
.gameArea {
width: 400px;
height: 650px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
background-color: rgb(0,0,0);
border: 2px solid rgb(255,255,255);
}
.gameAreaHide {
display: none;
}
.resultField {
width: 100%;
height: 20%;
padding: 0px 5px;
display: flex;
align-items: center;
justify-content: space-around;
}
.resultField div {
width: 48%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: rgb(255,255,255);
border: 2px solid rgb(0,0,0);
color: rgb(32, 39, 58);
}
#playerDisplay {
font-size: 16px;
letter-spacing: 1px;
border-bottom: 1px solid rgb(0,0,0);
height: 16%;
}
.displayXO {
font-family: 'Montserrat';
font-size: 18px;
}
.playerDisplayHide {
display: none;
}
.playerOne, .playerTwo {
height: 28%;
font-size: 26px;
font-weight: 800;
max-width: 98%;
overflow: hidden;
}
.resultPlayerOne, .resultPlayerTwo {
font-size: 44px;
height: 55%;
}
.messageField {
width: 100%;
height: 10%;
display: flex;
align-items: flex-end;
justify-content: center;
font-size: 22px;
letter-spacing: 1px;
color: white;
}
.messageField div {
display: flex;
align-items: baseline;
}
.playField {
width: 100%;
height: 60%;
padding: 0 5px 5px 5px;
display: flex;
flex-wrap: wrap;
align-content: flex-end;
justify-content: center;
}
.playFieldHide {
display: none;
}
.playField button {
width: 33%;
height: 33%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-family: 'Montserrat';
font-size: 110px;
font-weight: 400;
text-shadow: 1px 3px 7px rgba(0, 0, 0, 0.534);
transition: all 0.7s ease-in;
}
.firstColumn, .secondColumn, .thirdColumn {
background-color: rgb(0,0,0);
border: 2px solid rgb(255,255,255);
box-shadow: 0px 2px 10px rgb(102, 114, 146);
color: rgb(255,255,255);
}
.firstColumn, .secondColumn {
border-right: none;
}
.firstRow, .secondRow {
border-bottom: none;
}
.bleepWinner {
color: black;
background-color: rgb(255,255,255);
}
.winnerWindow {
display: none;
}
.winnerWindowShow {
width: 100%;
height: 60%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
padding-bottom: 25px;
}
.winner {
font-size: 65px;
font-family: 'Montserrat';
font-weight: 400;
letter-spacing: 10px;
color: white
}
.winnerName {
font-size: 40px;
padding-bottom: 35px;
color: white;
max-width: 90%;
overflow: hidden;
}
.playAgain {
width: 70%;
height: 50px;
font-size: 27px;
letter-spacing: 2px;
}
.resetGame {
width: 50%;
height: 40px;
font-size: 18px;
letter-spacing: 1px;
}
@media (max-width: 402px) {
.playerNames {
width: 300px;
height: 500px;
}
form div {
width: 80%;
height: 120px;
}
form button {
width: 70%;
letter-spacing: 1px;
padding: 10px 5px;
}
.gameArea {
width: 300px;
height: 500px;
}
#playerDisplay {
font-size: 16px;
letter-spacing: 1px;
border-bottom: none;
height: 16%;
}
.playerOne, .playerTwo {
font-size: 20px;
letter-spacing: 1px;
}
.resultPlayerOne, .resultPlayerTwo {
font-size: 26px;
}
.messageField, .takenMessageDiv {
font-size: 20px;
}
.playField {
padding: 0 5px 5px 5px;
}
.playField button {
font-size: 90px;
}
.winner {
font-size: 55px;
font-weight: 200;
letter-spacing: 8px;
}
.winnerName {
font-size: 50px;
font-weight: 400;
letter-spacing: 7px;
padding-bottom: 20px;
}
}
@media (max-width: 302px) {
.spanXO {
font-family: 'Montserrat';
font-size: 26px;
font-weight: 400;
}
.title {
padding-top: 3px;
font-size: 26px;
}
.playerNames {
width: 220px;
height: 350px;
}
form div {
width: 85%;
height: 100px;
}
label {
font-size: 20px;
}
form button {
width: 80%;
letter-spacing: 0px;
padding: 8px 5px;
font-size: 18px;
}
.gameArea {
width: 220px;
height: 350px;
}
.divPlayeOne, .divPlayeTwo {
border: 2px solid rgb(255,255,255);
}
#playerDIsplay {
font-size: 12px;
letter-spacing: 1px;
height: 20%;
}
.playerOne, .playerTwo {
font-size: 18px;
letter-spacing: 0px;
height: 30%;
}
.resultPlayerOne, .resultPlayerTwo {
font-size: 20px;
height: 50%;
}
.messageField, .takenMessageDiv {
font-size: 16px;
}
#playerDisplay {
font-size: 12px;
}
.displayXO {
font-size: 10px;
}
.playField {
padding: 0 3px 3px 3px;
}
.playField button {
font-size: 65px;
}
.winnerWindow {
padding-bottom: 2px;
}
.winner {
font-size: 45px;
font-weight: 200;
letter-spacing: 1px;
}
.winnerName {
font-size: 35px;
font-weight: 400;
letter-spacing: 1px;
padding-bottom: 10px;
}
.playAgain {
width: 70%;
height: 40px;
font-size: 20px;
letter-spacing: 1px;
padding: 5px, 8px;
}
.resetGame {
width: 50%;
height: 30px;
font-size: 16px;
letter-spacing: 0px;
padding: 10px, 15px;
}
}
</style>
<script>
const gameBoard = document.querySelectorAll('.playField button');
const messageField = document.querySelector('.messageField div');
const playField = document.querySelector('.playField');
const winnerWindow = document.querySelector('.winnerWindow');
let drawCount = 0;
const arrMoves = [[], [], []];
let playerX;
rollDice();
// to decide who is going to play first
function rollDice() {
let num = Math.floor(Math.random() * 20);
if (num % 2 === 0) {
playerX = true;
messageField.innerHTML = "Player <span class='spanXO'>X</span> starts";
}
else {
playerX = false
messageField.innerHTML = "Player <span class='spanXO'>O</span> starts";
}
}
// information about players
function playerNames(eventObject) {
eventObject.preventDefault();
//showing or diplaying their names on the screen
const playerOne = document.querySelector('.playerOne');
const playerTwo = document.querySelector('.playerTwo');
//choosing input text to catch players names
const namePlayerX = document.querySelector('#playerX');
const namePlayerO = document.querySelector('#playerO');
//displaying player names
if (namePlayerX.value === '') {
const playerDisplayX = document.querySelector('.playerDisplayOne');
playerDisplayX.classList.add('playerDisplayHide');
playerOne.innerText = 'Player X';
}
else
playerOne.innerText = namePlayerX.value;
if (namePlayerO.value === '') {
const playerDisplayX = document.querySelector('.playerDisplayTwo');
playerDisplayX.classList.add('playerDisplayHide');
playerTwo.innerText = 'Player O';
}
else
playerTwo.innerText = namePlayerO.value;
//stopping playerNames window
const playerNames = document.querySelector('.playerNames');
playerNames.classList.add('playerNamesHide');
namePlayerX.value = ''; //clearing name input
namePlayerO.value = '';
//starting gameArea window
const gameArea = document.querySelector('.gameArea');
gameArea.classList.remove('gameAreaHide');
}
function game() {
if (this.innerText) {
if (playerX)
messageField.innerHTML = "Spot taken. Player: <span class='spanXO'>X</span>";
else
messageField.innerHTML = "Spot taken. Player: <span class='spanXO'>O</span>";
}
else {
const checkForWinner = (move) => {
let isWinner = checkWinner(move);
if (isWinner) {
for (let btn of gameBoard) {
btn.disabled = true;
}
displayWinning(move);
}
else if (drawCount === 9)
displayDraw();
}
if (playerX) {
messageField.innerHTML = "Player: <span class='spanXO'>O</span>";
this.innerText = 'X';
playerX = false;
fillArray(this.id, this.innerText);
drawCount++;
checkForWinner(this.innerText);
}
else {
messageField.innerHTML = "Player: <span class='spanXO'>X</span>";
this.innerText = 'O';
playerX = true;
fillArray(this.id, this.innerText);
drawCount++;
checkForWinner(this.innerText);
}
}
}
function fillArray(id, move) {
switch (id) {
case 'one':
arrMoves[0][0] = move;
break;
case 'two':
arrMoves[0][1] = move;
break;
case 'three':
arrMoves[0][2] = move;
break;
case 'four':
arrMoves[1][0] = move;
break;
case 'five':
arrMoves[1][1] = move;
break;
case 'six':
arrMoves[1][2] = move;
break;
case 'seven':
arrMoves[2][0] = move;
break;
case 'eight':
arrMoves[2][1] = move;
break;
case 'nine':
arrMoves[2][2] = move;
break;
}
}
const blinkWinningField = function (direction, place) {
const addBleepWinner = (divArray) => {
for (let item of divArray) {
item.classList.add('bleepWinner');
}
}
if (direction === 'r') {
switch (place) {
case 0:
const rowDivsOne = document.querySelectorAll('.firstRow');
addBleepWinner(rowDivsOne);
break;
case 1:
const rowDivsTwo = document.querySelectorAll('.secondRow');
addBleepWinner(rowDivsTwo);
break;
case 2:
const rowDivsThree = document.querySelectorAll('.thirdRow');
addBleepWinner(rowDivsThree);
break;
}
}
else if (direction === 'c') {
switch (place) {
case 0:
const colDivsOne = document.querySelectorAll('.firstColumn');
addBleepWinner(colDivsOne);
break;
case 1:
const colDivsTwo = document.querySelectorAll('.secondColumn');
addBleepWinner(colDivsTwo);
break;
case 2:
const colDivsThree = document.querySelectorAll('.thirdColumn');
addBleepWinner(colDivsThree);
break;
}
}
else if (direction === 'ddown') {
const dDownDivs = document.querySelectorAll('.diagonalDown');
addBleepWinner(dDownDivs);
}
else {
const dUpDivs = document.querySelectorAll('.diagonalUp');
addBleepWinner(dUpDivs);
}
}
function checkWinner(move) {
for (let r = 0; r < 3; r++) {
if (arrMoves[r][0] === move && arrMoves[r][1] === move && arrMoves[r][2] === move) {
scoreTracker(move);
blinkWinningField('r', r);
return true;
}
}
for (let c = 0; c < 3; c++) {
if (arrMoves[0][c] === move && arrMoves[1][c] === move && arrMoves[2][c] === move) {
scoreTracker(move);
blinkWinningField('c', c);
return true;
}
}
if (arrMoves[0][0] === move && arrMoves[1][1] === move && arrMoves[2][2] === move) {
scoreTracker(move);
blinkWinningField('ddown', null);
return true;
}
if (arrMoves[0][2] === move && arrMoves[1][1] === move && arrMoves[2][0] === move) {
scoreTracker(move);
blinkWinningField('dup', null);
return true;
}
return false;
}
function displayWinning(winner) {
setTimeout(() => {
const winnerWindow = document.querySelector('.winnerWindow');
const winnerName = document.querySelector('.winnerName');
const playerX = document.querySelector('.playerOne');
const playerO = document.querySelector('.playerTwo');
if (winner === 'X')
winnerName.innerText = playerX.innerText;
else
winnerName.innerText = playerO.innerText;
playField.classList.add('playFieldHide');
messageField.innerText = '';
winnerWindow.classList.add('winnerWindowShow');
}, 1500);
}
function displayDraw() {
const winner = document.querySelector('.winner');
const winnerName = document.querySelector('.winnerName');
playField.classList.add('playFieldHide');
messageField.innerText = '';
winnerWindow.classList.add('winnerWindowShow');
winner.innerText = 'DRAW'
winnerName.innerText = ' ';
}
function scoreTracker(move) {
const playerX = document.querySelector('.resultPlayerOne');
const playerO = document.querySelector('.resultPlayerTwo');
if (move === 'X')
playerX.innerText++;
else
playerO.innerText++;
}
function resetGameBoard() {
rollDice();
drawCount = 0; //start at zero again
for (let r = 0; r < 3; r++) {
for (let c = 0; c < 3; c++) {
arrMoves[r][c] = '';
}
}
for (let btn of gameBoard) {
btn.innerText = '';
btn.classList.remove('bleepWinner');
btn.disabled = false;
}
const winner = document.querySelector('.winner');
winner.innerText = 'WINNER';
playField.classList.remove('playFieldHide');
winnerWindow.classList.remove('winnerWindowShow');
}
function resetScoreTracker() {
const playerX = document.querySelector('.resultPlayerOne');
const playerO = document.querySelector('.resultPlayerTwo');
playerX.innerText = 0;
playerO.innerText = 0;
}
const form = document.querySelector('form');
form.addEventListener('submit', playerNames);
for (let btn of gameBoard) {
btn.addEventListener('click', game);
}
const resetGameButton = document.querySelector('.resetGame');
resetGameButton.addEventListener('click', () => {
resetGameBoard();
resetScoreTracker();
const playerNames = document.querySelector('.playerNames');
playerNames.classList.remove('playerNamesHide');
const gameArea = document.querySelector('.gameArea');
gameArea.classList.add('gameAreaHide');
const playerDisplayX = document.querySelector('.playerDisplayOne');
playerDisplayX.classList.remove('playerDisplayHide');
const playerDisplayO = document.querySelector('.playerDisplayTwo');
playerDisplayO.classList.remove('playerDisplayHide');
})
const playAgainButton = document.querySelector('.playAgain');
playAgainButton.addEventListener('click', resetGameBoard)
</script>
</html>Output images:




Also Read:
- Download 1000+ Projects, All B.Tech & Programming Notes, Job, Resume & Interview Guide, and More – Get Your Ultimate Programming Bundle!
- What is web development for beginners?
- Music Recommendation System in Machine Learning
- Brick Breaker Game in C++
- 100+ Java Projects for Beginners 2023
- Chat App with Node.js and Socket.io
- Draw Doraemon using HTML and CSS
- Draw House using HTML and CSS
- Best JavaScript Projects for Beginners in 2023
- Draw Dog using CSS
- Rock Paper Scissor in HTML CSS JavaScript
- Pong Game in HTML and JavaScript
- Tip Calculator in HTML and JavaScript
- Calculator in HTML CSS JavaScript
- BMI Calculator in HTML CSS JavaScript
- Color picker in HTML and JavaScript
- Number Guessing Game in JavaScript
- Best Java Roadmap for Beginners 2023
- ATM in JavaScript
- Inventory Management System in JavaScript
- Courier Tracking System in HTML CSS and JS
- Word Count App in JavaScript
- Test Typing Speed using Python App
- Top 10 PHP Projects with Source Code
- To-Do List in HTML CSS JavaScript
- Tic-Tac-Toe game in JavaScript
- Music player using HTML CSS and JavaScript
- Top 20 Django Projects
- Happy Diwali in JavaSCript
- Top 15 Android Projects for Resume
- Top 15 Machine Learning Projects in Python with source code
- Top 15 Java Projects For Resume
- Top 10 Java Projects with source code



