Tic-Tac-Toe Game Using ReactJS

Introduction

 
Tic-Tac-Toe (also called Noughts and Crosses) is a very simple game in which two players alternately put Xs and Os in compartments of a figure formed by two vertical lines crossing two horizontal lines. Each player tries to get a row of three Xs or three Os before the opponent does. The player who succeeds in placing three of their marks in a horizontal, vertical, or diagonal row is the winner.

Tic-Tac-Toe Game Using ReactJSApplication
  • Players: 2
  • Skill(s) required: Strategy, tactics, observation
  • Genres: Paper-and-pencil game, Board game, Strategy game

For the Design Board


The design is based on 3 X 3 Grid design for the game. We need to first create the board design with a 3 X 3 block. The footer counting section is designed to determine how many times the player or the computer wins the game, as well as the count of tie games between the computer and player.
 
Tic-Tac-Toe Game Using ReactJSApplication 
  1. render() {    
  2.   return (    
  3.     <div className="App">    
  4.       <div className="game">    
  5.         <div className="board">    
  6.           <div onClick={() => this.handleClick(1)} className="square top left" ><div ref="block1"></div></div>    
  7.           <div onClick={() => this.handleClick(2)} className="square top" ><div ref="block2"></div></div>    
  8.           <div onClick={() => this.handleClick(3)} className="square top right" ><div ref="block3"></div></div>    
  9.           <div onClick={() => this.handleClick(4)} className="square left" ><div ref="block4"></div></div>    
  10.           <div onClick={() => this.handleClick(5)} className="square" ><div ref="block5"></div></div>    
  11.           <div onClick={() => this.handleClick(6)} className="square right" ><div ref="block6"></div></div>    
  12.           <div onClick={() => this.handleClick(7)} className="square bottom left" ><div ref="block7"></div></div>    
  13.           <div onClick={() => this.handleClick(8)} className="square bottom" ><div ref="block8"></div></div>    
  14.           <div onClick={() => this.handleClick(9)} className="square bottom right" ><div ref="block9"></div></div>    
  15.         </div>    
  16.       </div>    
  17.       <div class="scores p1">    
  18.         <p class="player1"><span class="p1">Player</span><span class="p2">Player 1</span> (<span class="x"></span>)<span class="score">{this.state.playerWin}</span></p>    
  19.         <p class="ties">Tie<span class="score">{this.state.tieGames}</span></p>    
  20.         <p class="player2"><span class="p1">Computer</span><span class="p2">Player 2</span> (<span class="o"></span>)<span class="score">{this.state.computerWin}</span></p>    
  21.       </div>    
  22.     </div>    
  23.   );    
  24. }    

Default Configurations

 
Consider the player step as 'X' and the computer step as 'O' in the game. As everything is developed in React JS, we need to maintain the state of each required thing via the state in React Js. We need to take care of the state of the following things for built-up game logic.
  • Winner Status
  • Total Player Clicks
  • Total Computer Clicks
  • Block is Clickable or not(This status is for automatically perform by computer, We need to hold player interaction to be performing for next move until computer move occurs)
  • Counting of tied games, the computer wins and the player wins

Developed Logic For Game 

 
When the user starts the game or the page is loaded, the player's turn will be the next step up. Each block, we have to perform the following conditions or operations while clicked by the player or automatically clicked by a computer player.

STEP 1 - Block Click Event
 
We need to check whether a block that is clicked has been already occupied earlier or not. If yes, then there's no need to perform any further process.     
  1. handleClick = (index) => {    
  2.   if (!this.state.isClickable) {    
  3.     return;    
  4.   }    
  5.     
  6.   if (this.refs["block" + index].className.length > 0) {    
  7.     return;    
  8.   }    
  9.     
  10.   if (this.state.isWinner) {    
  11.     return;    
  12.   }    
  13.     
  14.   this.refs["block" + index].className = "x";    
  15.   this.refs["block" + index].classList.add('x');    
  16.   this.checkForWinner();    
  17.   this.setState({    
  18.     userClick: parseInt(this.state.userClick) + 1,    
  19.     isClickable: false    
  20.   }, () => {    
  21.     this.computerTurn(index);    
  22.   });    
  23. }    
STEP 2
 
In the case that the block is not occupied, then we need to check it as 'X'. Now we need to check the verification of the winning condition.
 
Tic-Tac-Toe Game Using ReactJSApplication
 
STEP 3 - Winning Condition
 
combination collection = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 4, 7], [2, 5, 8], [3, 6, 9], [1, 5, 9], [3, 5, 7]];
 
Here, the combination collection is the possible combinations that could be possible ways to verify the winner after clicked by a player. We need to verify if the player wins or not. If a player wins, then the game automatically resets after 3 seconds. Otherwise, it will move to a further process. We need to add one more count of the player who wins here. 
  1. checkForWinner = () => {    
  2.   const combinationCollection = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 4, 7], [2, 5, 8], [3, 6, 9], [1, 5, 9], [3, 5, 7]];    
  3.   combinationCollection.map((data) => {    
  4.     if ((this.refs["block" + data[0]].className && this.refs["block" + data[1]].className && this.refs["block" + data[2]].className)    
  5.       && (this.refs["block" + data[0]].className.toLowerCase() === this.refs["block" + data[1]].className.toLowerCase() && this.refs["block" + data[1]].className.toLowerCase() === this.refs["block" + data[2]].className.toLowerCase() && this.refs["block" + data[2]].className.toLowerCase() === this.refs["block" + data[0]].className.toLowerCase())) {    
  6.       {    
  7.         this.setState({    
  8.           isWinner: true,    
  9.           isUserWinnder: (this.refs["block" + data[0]].className === "x"),    
  10.           playerWin: (this.refs["block" + data[0]].className === "x") ? (parseInt(this.state.playerWin) + 1) : this.state.playerWin,    
  11.           computerWin: (this.refs["block" + data[0]].className === "o") ? (parseInt(this.state.computerWin) + 1) : this.state.computerWin    
  12.         }, () => {    
  13.           this.refs["block" + data[0]].classList.add('blink');    
  14.           this.refs["block" + data[1]].classList.add('blink');    
  15.           this.refs["block" + data[2]].classList.add('blink');    
  16.           setTimeout(() => {    
  17.             this.resetGame();    
  18.           }, 2000);    
  19.         });    
  20.       }    
  21.     }    
  22.   });    
  23. }   
Reset Game Function
  1. resetGame = () => {    
  2.   for (let i = 1; i <= 9; i++) {    
  3.     this.refs["block" + i].classList = "";    
  4.   }    
  5.     
  6.   this.setState({    
  7.     userClick: 0,    
  8.     computerClick: 0,    
  9.     isWinner: false,    
  10.     isClickable: true    
  11.   });    
  12. }     
STEP 4
 
Now it's the computer's turn, so we need to make the step automated.
 
For that, we need to check "How many blocks remain occupied. We need to automatically select a random place and make it select it automatically". After this, we need to verify the winner again. If the computer wins, then the game automatically resets after 3 seconds. Otherwise, it will move to a further process. We need to add one more count of the computer wins here.
  1. computerTurn = () => {    
  2.   if (this.state.isWinner) {    
  3.     return;    
  4.   }    
  5.     
  6.   let notBlueOrRed = [];    
  7.   let isAvailable = false;    
  8.   for (let i = 1; i <= 9; i++) {    
  9.     if (this.refs["block" + i].className.length === 0) {    
  10.       notBlueOrRed.push(i);    
  11.       isAvailable = true;    
  12.     }    
  13.   }    
  14.     
  15.   if (isAvailable) {    
  16.     setTimeout(() => {    
  17.       var randomItem = notBlueOrRed[Math.floor(Math.random() * notBlueOrRed.length)];    
  18.       this.refs["block" + randomItem].className = "o";    
  19.       this.refs["block" + randomItem].classList.add('o');    
  20.       this.checkForWinner();    
  21.       this.setState({    
  22.         computerClick: parseInt(this.state.computerClick) + 1,    
  23.         isClickable: true    
  24.       });    
  25.     }, 1000);    
  26.   } else {    
  27.     if (!this.state.isWinner) {    
  28.       this.setState({    
  29.         tieGames: parseInt(this.state.tieGames) + 1    
  30.       }, () => {    
  31.         setTimeout(() => {    
  32.           this.resetGame();    
  33.         }, 2000);    
  34.       });    
  35.     }    
  36.   }    
  37. }   
STEP 5
 
If the last block is available and the player clicks on it, we need to again verify the winner. If the player wins, then we need to reset the game and add one more count to the player wins. Otherwise, add one more count to tie game counting.

The above steps are the logical flow of the game, which must need to be implemented for the game.
That's all. I hope you all enjoy it.