How to Make Tic Tac Toe Using React

In this article, we will make a very famous game Tic Tac Toe using react. Since tic tac toe is a very famous and cool game it gives some nostalgia for our childhood memories. Also, this game is so popular among the developers, and they have made this game in many other programming languages.

As we know that JavaScript is so popular among developers, we will make this game using ReactJS. In this we will design the board for it and also, it will be a two-player game. We will add some logic to identify the winning conditions, and we will make a count of the wins for ‘x’ and ‘o’.

What is the Tic Tac Toe Game?

Tic Tac Toe is a two-player game in which the objective is to take turns and mark the correct spaces in a 3×3 (or larger) grid. Think on your feet but also be careful, as the first player who places three of their marks in a horizontal, vertical, or diagonal row wins the game. So this is the objective of this game, one player has an ‘x’ and the other one has an ‘o’ sign.

Pre-requisites to Make Tic Tac Toe Using React

  • Basic knowledge of React Props
  • Good knowledge of React Components, and hooks.
  • Basic concepts of React

Creating The Boxes

Now firstly we need to create the boxes for the game, for that, we have created a component for boxes named Box.js. In this component, we have passed value and onClick as the props that come from the App.js component. Initially, these have a null value in each of these props.

In Box, we are adding the constant in which we are checking, if a value is ‘x’ or ‘o’, if a condition is true then we are adding box x, and if it is false then add box o. So these are class names that are assigned dynamically. Hence, we have added a button, in which we are adding the value of the style constant as the class name. And we are modifying the value as the onClick event gets triggered.

Then we applied some basic CSS to this button and added some basic conditional CSS as well.

App.js

import { Box } from "./components/Box";

 function App(){  
  return (
    <div className="App">
      <Box value="X" onClick={null}/>
    </div>
  );
}

export default App;

Box.js

import React from 'react';

import "./Box.css";

export const Box = ({ value, onClick }) => {
    const style = value === "X" ? "box x" : "box o";

    return (
        <button className={style} onClick={onClick}>{value}</button>
    )
}

Box.css

.box {
  background-color: #ffffff;
  border: none;
  border-radius: 10%;
  box-shadow: 0px 0px 8px #888888;
  width: 5rem;
  height: 5rem;
  text-align: center;
  font-size: 5em;
  font-family: "Fredoka", sans-serif;
  font-weight: bold;
  line-height: 5rem;
  margin: 0.5rem;
}

.x {
  color: rgb(255, 70, 37);
}

.o {
  color: rgb(44, 135, 255);
}

.box:hover {
  box-shadow: 0px 0px 15px #888888;
}
Tic Tac Toe

Arranging The Boxes

Now we have created only one box and styled it, So we just need to add 8 more boxes to arrange them in a 3×3 grid. For that, we have added another component named Board, in this component we will manage the boxes. Since we are going to create the boxes through this Board component, we will remove the Box component from the App.js Component import our Board.js component, and apply the same props as before. In this Board component, we will add the logic for the Box component.

Then in the Board.js component, we copied the same code that we had added before in the App.js for the box component. We will apply the map() method here so that we can add the 9 buttons. Here we have added onClick={() => value === null && onClick(idx), so that we can control player selection, by doing this we cannot change the box value by clicking it again. Then we applied some CSS-like grid property, so the boxes will be arranged in the 3×3 boxes.

App.js

import React, { useState } from "react";

import { Board } from "./components/Board";

import './App.css';

const App = () => {

  const board = ["X","X","X","X","X","X","X","X","X"]

  return (
    <div className="App">
      <Board board={board} onClick={null} />
      
    </div>
  );
}

export default App;

Board.js

import React from 'react'

import { Box } from "./Box"
import "./Board.css"

export const Board = ({ board, onClick }) => {
  return (
    <div className="board">
      {
        board.map((value, idx) => {
          return <Box value={value} onClick={() => value === null && onClick(idx)} />;
        })
      }
    </div>
  )
}

Board.css

.board {
  display: grid;
  grid-template-columns: repeat(3, 6rem);
  place-items: center;
  justify-content: center;
}
Tic Tac Toe

Adding The Game Logic

Now we need to add the game logic, before that we need to remove static constant buttons, and we will add a state hook named board in which we have added an array of 9 sizes with null value initially. Then we have added a function handleBoxClick on onClick event, In this function, we are adding the map() method to modify the value. We also declared another state hook, in which we have initially added true. Then we will return X if the value of state is true, if it is false then we will add O. We will update the board again using the setBoard hook.

Now we need to change the value every second click, so for that, we have set our xPlaying state to !xPlaying which will return an alternative value every time it triggers.

App.js

import React, { useState } from "react";

import { Board } from "./components/Board";

import './App.css';

const App = () => {

  const [xPlaying, setXPlaying] = useState(true);
  const [board, setBoard] = useState(Array(9).fill(null))
  

  const handleBoxClick = (boxIdx) => {
    // Step 1: Update the board
    const updatedBoard = board.map((value, idx) => {
      if (idx === boxIdx) {
        return xPlaying ? "X" : "O";
      } else {
        return value;
      }
    })

    setBoard(updatedBoard);

  

    
    setXPlaying(!xPlaying);
  }


  return (
    <div className="App">
     
      <Board board={board} onClick={handleBoxClick} />
      
    </div>
  );
}

export default App;
Tic Tac Toe

Detecting The Winner

Since we have done the main logic like switching turns and also created a board, no we need to detect the winner. For that, we have added an array in which we have added winning conditions, where we have mentioned some winning conditions like if X spotted on 0,1,2 position which is the first row of the board. Then we have declared a function for checking the winner, in this function, we have added a loop till array size. It will iterate through win conditions and check if either player satisfies them, and we will return the player who satisfies the condition. We also added a message to get the winner, but it will be temporary.

import React, { useState } from "react";

import { Board } from "./components/Board";

import './App.css';

const App = () => {

  const WIN_CONDITIONS = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6]
  ]

  const [xPlaying, setXPlaying] = useState(true);
  const [board, setBoard] = useState(Array(9).fill(null))
  

  const handleBoxClick = (boxIdx) => {
    // Step 1: Update the board
    const updatedBoard = board.map((value, idx) => {
      if (idx === boxIdx) {
        return xPlaying ? "X" : "O";
      } else {
        return value;
      }
    })

    setBoard(updatedBoard);

    // Step 2: Check if either player has won the game
    const winner = checkWinner(updatedBoard);

    

    // Step 3: Change active player
    setXPlaying(!xPlaying);
  }

  const checkWinner = (board) => {
    for (let i = 0; i < WIN_CONDITIONS.length; i++) {
      const [x, y, z] = WIN_CONDITIONS[i];

      // Iterate through win conditions and check if either player satisfies them
      if (board[x] && board[x] === board[y] && board[y] === board[z]) {
        document.write(`winner is ${board[x]}`);
        return board[x];
        
      }
    }
  }

 

  return (
    <div className="App">
      
      <Board board={board} onClick={handleBoxClick} />
      
    </div>
  );
}

export default App;
Tic Tac Toe

Adding Score Board

Now we need to scoreboard, for that we have added a component named ScoreBoard.js. In this, we are getting props from the App.js component for scores and xPlaying to get the current score and player. Then we added these scores in some variables, and then we just added 2 spans, in which we added players and their corresponding scores. We also added some smaller CSS for these two spans.

Now in the App.js component, we have added another state for score with default values. Then we are checking the condition, in which, if we get the winner, then we are just updating the state with increased value.

import React, { useState } from "react";

import { Board } from "./components/Board";

import { ScoreBoard } from "./components/ScoreBoard";
import './App.css';

const App = () => {

  const WIN_CONDITIONS = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6]
  ]

  const [xPlaying, setXPlaying] = useState(true);
  const [board, setBoard] = useState(Array(9).fill(null))
  const [scores, setScores] = useState({ xScore: 0, oScore: 0 })
  

  const handleBoxClick = (boxIdx) => {
    // Step 1: Update the board
    const updatedBoard = board.map((value, idx) => {
      if (idx === boxIdx) {
        return xPlaying ? "X" : "O";
      } else {
        return value;
      }
    })

    setBoard(updatedBoard);

    // Step 2: Check if either player has won the game
    const winner = checkWinner(updatedBoard);

    if (winner) {
      if (winner === "O") {
        let { oScore } = scores;
        oScore += 1;
        setScores({ ...scores, oScore })
      } else {
        let { xScore } = scores;
        xScore += 1;
        setScores({ ...scores, xScore })
      }
    }

    // Step 3: Change active player
    setXPlaying(!xPlaying);
  }

  const checkWinner = (board) => {
    for (let i = 0; i < WIN_CONDITIONS.length; i++) {
      const [x, y, z] = WIN_CONDITIONS[i];

      // Iterate through win conditions and check if either player satisfies them
      if (board[x] && board[x] === board[y] && board[y] === board[z]) {
        
        return board[x];
      }
    }
  }

  

  return (
    <div className="App">
      <ScoreBoard scores={scores} xPlaying={xPlaying} />
      <Board board={board} onClick={handleBoxClick} />
      
    </div>
  );
}

export default App;

ScoreBoard.js

import React from 'react'

import "./ScoreBoard.css"

export const ScoreBoard = ({ scores, xPlaying }) => {
  const { xScore, oScore } = scores;

  return (
    <div className="scoreboard">
      <span className={`score x-score ${!xPlaying && "inactive"}`}>X - {xScore}</span>
      <span className={`score o-score ${xPlaying && "inactive"}`}>O - {oScore}</span>
    </div>
  )
}
Tic Tac Toe

Resetting The Board

Now we have almost done most of the things, we just need to add a reset button. For that, we have added the ResetButton.js component. In this, we have added a button with an onClick event. Now we will move to App.js, In this we will add another state for the game over with a default false value. Then we updated the value to true after we got the winner, then we also added a function in which we again updated the value to false, and then we added a null value to every box of the board.

import React, { useState } from "react";

import { Board } from "./components/Board";
import { ResetButton } from "./components/ResetButton";
import { ScoreBoard } from "./components/ScoreBoard";
import './App.css';

const App = () => {

  const WIN_CONDITIONS = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6]
  ]

  const [xPlaying, setXPlaying] = useState(true);
  const [board, setBoard] = useState(Array(9).fill(null))
  const [scores, setScores] = useState({ xScore: 0, oScore: 0 })
  const [gameOver, setGameOver] = useState(false);

  const handleBoxClick = (boxIdx) => {
    // Step 1: Update the board
    const updatedBoard = board.map((value, idx) => {
      if (idx === boxIdx) {
        return xPlaying ? "X" : "O";
      } else {
        return value;
      }
    })

    setBoard(updatedBoard);

    // Step 2: Check if either player has won the game
    const winner = checkWinner(updatedBoard);

    if (winner) {
      if (winner === "O") {
        let { oScore } = scores;
        oScore += 1;
        setScores({ ...scores, oScore })
      } else {
        let { xScore } = scores;
        xScore += 1;
        setScores({ ...scores, xScore })
      }
    }

    // Step 3: Change active player
    setXPlaying(!xPlaying);
  }

  const checkWinner = (board) => {
    for (let i = 0; i < WIN_CONDITIONS.length; i++) {
      const [x, y, z] = WIN_CONDITIONS[i];

      // Iterate through win conditions and check if either player satisfies them
      if (board[x] && board[x] === board[y] && board[y] === board[z]) {
        setGameOver(true);
        return board[x];
      }
    }
  }

  const resetBoard = () => {
    setGameOver(false);
    setBoard(Array(9).fill(null));
  }

  return (
    <div className="App">
      <ScoreBoard scores={scores} xPlaying={xPlaying} />
      <Board board={board} onClick={gameOver ? resetBoard : handleBoxClick} />
      <ResetButton resetBoard={resetBoard} />
    </div>
  );
}

export default App;

ResetButton.js

import React from 'react';

import "./ResetButton.css";

export const ResetButton = ({ resetBoard }) => {
    return (
        <button className="reset-btn" onClick={resetBoard}>Reset</button>
    )
}
Tic Tac Toe

Full Source Code of Tic Tac Toe in React

App.js

import React, { useState } from "react";

import { Board } from "./components/Board";
import { ResetButton } from "./components/ResetButton";
import { ScoreBoard } from "./components/ScoreBoard";
import './App.css';

const App = () => {

  const WIN_CONDITIONS = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6]
  ]

  const [xPlaying, setXPlaying] = useState(true);
  const [board, setBoard] = useState(Array(9).fill(null))
  const [scores, setScores] = useState({ xScore: 0, oScore: 0 })
  const [gameOver, setGameOver] = useState(false);

  const handleBoxClick = (boxIdx) => {
    // Step 1: Update the board
    const updatedBoard = board.map((value, idx) => {
      if (idx === boxIdx) {
        return xPlaying ? "X" : "O";
      } else {
        return value;
      }
    })

    setBoard(updatedBoard);

    // Step 2: Check if either player has won the game
    const winner = checkWinner(updatedBoard);

    if (winner) {
      if (winner === "O") {
        let { oScore } = scores;
        oScore += 1;
        setScores({ ...scores, oScore })
      } else {
        let { xScore } = scores;
        xScore += 1;
        setScores({ ...scores, xScore })
      }
    }

    // Step 3: Change active player
    setXPlaying(!xPlaying);
  }

  const checkWinner = (board) => {
    for (let i = 0; i < WIN_CONDITIONS.length; i++) {
      const [x, y, z] = WIN_CONDITIONS[i];

      // Iterate through win conditions and check if either player satisfies them
      if (board[x] && board[x] === board[y] && board[y] === board[z]) {
        setGameOver(true);
        return board[x];
      }
    }
  }

  const resetBoard = () => {
    setGameOver(false);
    setBoard(Array(9).fill(null));
  }

  return (
    <div className="App">
      <ScoreBoard scores={scores} xPlaying={xPlaying} />
      <Board board={board} onClick={gameOver ? resetBoard : handleBoxClick} />
      <ResetButton resetBoard={resetBoard} />
    </div>
  );
}

export default App;

Box.js

import React from 'react';

import "./Box.css";

export const Box = ({ value, onClick }) => {
    const style = value === "X" ? "box x" : "box o";

    return (
        <button className={style} onClick={onClick}>{value}</button>
    )
}

Board.js

import React from 'react'

import { Box } from "./Box"
import "./Board.css"

export const Board = ({ board, onClick }) => {
  return (
    <div className="board">
      {
        board.map((value, idx) => {
          return <Box value={value} onClick={() => value === null && onClick(idx)} />;
        })
      }
    </div>
  )
}

ScoreBoard.js

import React from 'react'

import "./ScoreBoard.css"

export const ScoreBoard = ({ scores, xPlaying }) => {
  const { xScore, oScore } = scores;

  return (
    <div className="scoreboard">
      <span className={`score x-score ${!xPlaying && "inactive"}`}>X - {xScore}</span>
      <span className={`score o-score ${xPlaying && "inactive"}`}>O - {oScore}</span>
    </div>
  )
}

ResetButton.js

import React from 'react';

import "./ResetButton.css";

export const ResetButton = ({ resetBoard }) => {
    return (
        <button className="reset-btn" onClick={resetBoard}>Reset</button>
    )
}

Check out the video reference here:

You may also like:

Reactjs Guru
Reactjs Guru

Welcome to React Guru, your ultimate destination for all things React.js! Whether you're a beginner taking your first steps or an experienced developer seeking advanced insights.

React tips & tutorials delivered to your inbox

Don't miss out on the latest insights, tutorials, and updates from the world of ReactJs! Our newsletter delivers valuable content directly to your inbox, keeping you informed and inspired.

3 Comments

  1. […] Tic Tac Toe Oyunu Nedir?Tic Tac Toe, amacın sırayla 3 × 3 (veya daha büyük) bir ızgarada doğru boşlukları işaretlemek olduğu iki oyunculu bir oyundur. Ayaklarınızın üzerinde düşünün ama aynı zamanda dikkatli olun, çünkü işaretlerinden üçünü yatay, dikey veya çapraz sıraya yerleştiren ilk oyuncu oyunu kazanır. Yani bu oyunun amacı bu, bir oyuncunun ‘x’ ve diğerinin ‘o’ işareti var.devamını oku […]

Leave a Reply

Your email address will not be published. Required fields are marked *

Table of Contents