Let's build an AI Tic-Tac-Toe in React within 1 hour
Tags: react, ai, javascript, webdev
Published: 2022-07-06 09:20:07

Hello, Let's build an AI tic-tac-toe today in React. Just a small note before we start, we'll not be using any Mini-Max AI algorithms to build the game. Instead, we are going to use the [tictactoeAPI](https://rapidapi.com/stujo/api/tic-tac-toe/). Here is the link to the [game](https://Sadeedpv.github.io/AIgame) and the Github [repo](https://github.com/Sadeedpv/AIgame). It will be easier for you to follow the tutorial if you have some basic knowledge of React.

First of all, let's create the react-app with the command
`npx-create-react-app tictactoe`

Delete the boilerplate code and you should see a blank page when you run the command `npm start`. Our folder structure will be quite straightforward with a components folder inside the src folder. Our index.js file should look like this:

```
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <>
     <Header />
     <AI/>
  
  </>
);

```
Now our task is to create these two components. Let's start with the Header file which is really simple.

```
import React from 'react'

function Header() {
  return (
    <div style={{
        display:'flex',
        alignItems:'cemter',
        justifyContent:'center',
        padding:'10px',
        marginTop:'1.4em',
        fontWeight:'650',
        fontSize:'1.4rem'
    }}>Let's Play Tac-Tac-Toe 👍</div>
  )
}

export default Header
```
The AI component is the complicated one, but let's break it down.

```
import React from 'react'
import axios from 'axios'

function AI(){
return(
     <div style={{
        display:'flex',
        flexDirection:'column',        
        alignItems:'center',
        justifyContent:'center'
    }}>
      
    </div>
)
}
```

Here we have an outer div to place all its contents in the center of the webpage. Then, we are going to build a reset button.

 

```
   <div style={{
        display:'flex',
        alignItems:'center',
        flexDirection:'row',
        flexWrap:'wrap',
        justifyContent:'center',
        marginTop:'-16px'
    }}>
      {* Reset button *}
      <button 
        style={{
            color:'red'
        }}>Reset</button>

    </div>

```

Then, we need to declare some states

```
    const [winner, setwinner] = React.useState('No winner');
    const [undo, setundo] = React.useState(null);

    const [board, setboard] = React.useState({
        '0': '-',
        '1': '-',
        '2': '-',
        '3': '-',
        '4': '-',
        '5': '-',
        '6': '-',
        '7': '-',
        '8': '-'
    })

    const [turn, setturn] = React.useState('X');
```
We need to tell the user whose turn is and who won the game, so:

```
    <div>{turn} turn!</div>

    <div>{ winner && winner !== 'No winner' ? (`${winner} won!`):'No one won!'}    
    </div>
```
Let's add some styling:

```
    <div style={{
        fontSize:'25px',
        padding:'3px',
        fontWeight:'650'
    }}>{turn} turn!</div>

    <div style={{
        display:'flex',
        alignItems:'center',
        justifyContent:'center',
        fontSize:'25px',
        color:'green'
    }}>{ winner && winner !== 'No winner' ? (`${winner} won!`):'No one won!'}    
    </div>
```

It's time to create the table component

```
    <table>
        <tbody>
        <tr>
            <td onClick={() =>{
                handleEvent(0);
            }}> {board['0']} </td>
            <td onClick={() =>{
                handleEvent(1)
            }}> { board['1']} </td>
            <td onClick={() =>{
                handleEvent(2)
            }}> {board['2']} </td>
        </tr>
        <tr>
            <td onClick={() =>{
                handleEvent(3)
            }}> {board['3']} </td>
            <td onClick={() =>{
                handleEvent(4)
            }}> {board['4']} </td>
            <td onClick={() =>{
                handleEvent(5)
            }}> {board['5']} </td>
        </tr>
        <tr>
            <td onClick={() =>{
                handleEvent(6)
            }}> {board['6']} </td>
            <td onClick={() =>{
                handleEvent(7)
            }}> {board['7']} </td>
            <td onClick={() =>{
                handleEvent(8)
            }}> {board['8']} </td>
        </tr>
        </tbody>
    </table>
```

Let's add some more styling:

```
table{
    background-color: white;
    border: 2px solid #1b1b32;

}

td{
    border: 2px solid #1b1b32;
    padding: 40px;
    align-items: center;
}

td:hover{
    background-color: azure;
}

@media (max-width:485px){
    td{
        padding: 25px;
    }
}
```
Our website should look like this:

![Ai tic-tac-toe](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2l17nnzrbmz2eaillku9.png)

Now, it's time to handle the logic of the game. Right now, we have an onClick event handler on every td element. So let's create that  function.

```
   function handleEvent(e){
        setundo(e);
        setboard(prevstate => ({...prevstate, [e]: 'O'}))
    }
```

Right now the user could play O on every square. So we need to add a condition to make sure that the user does not play O on the same square already played. So let's rewrite the function as:

```
   function handleEvent(e){
        if (board[e] === '-' && winner === 'No winner'){
            setundo(e);
            setboard(prevstate => ({...prevstate, [e]: 'O'}))
            
        }
    }
```

```
    // Check for winners

    React.useEffect(() =>{
        if (board['0'] === board['1'] && board['1'] === board['2'] && board['2'] !== '-'){
            setwinner(board['0'])
        }
        else if(board['3'] === board['4'] && board['4'] === board['5'] && board['5'] !== '-'){
            setwinner(board['3'])
        }
        else if(board['6'] === board['7'] && board['7'] === board['8'] && board['8'] !== '-'){
            setwinner(board['6'])
        }
        else if(board['0'] === board['3'] && board['3'] === board['6'] && board['6'] !== '-'){
            setwinner(board['0'])
        }
        else if(board['1'] === board['4'] && board['4'] === board['7'] && board['7'] !== '-'){
            setwinner(board['1'])
        }
        else if(board['2'] === board['5'] && board['5'] === board['8'] && board['8'] !== '-'){
            setwinner(board['2'])
        }
        else if(board['0'] === board['4'] && board['4'] === board['8'] && board['8'] !== '-'){
            setwinner(board['0'])
        }
        else if(board['2'] === board['4'] && board['4'] === board['6'] && board['6'] !== '-'){
            setwinner(board['2'])
        }
    }, [board])
```

The above part is to check whether anyone has won the game whenever the state of the board changes.
Remember the button we made(Reset button). Let's add logic to that as well.

```
        <button 
        onClick={() =>{
            setwinner('No winner');
            setboard({
                '0': '-',
                '1': '-',
                '2': '-',
                '3': '-',
                '4': '-',
                '5': '-',
                '6': '-',
                '7': '-',
                '8': '-'
            });
            setundo(null);
        }}>Reset</button>
```
Now comes the API part of the game. I recommend you to go through the API [documentation](https://rapidapi.com/stujo/api/tic-tac-toe/) to get a more clear idea of what's happening. So, this time, we are going to create another useEffect.

```
    React.useEffect(() =>{

        var game = [board[0], board[1], board[2], board[3], board[4], board[5], board[6], board[7], board[8]];
        game = game.join('');

        
    const options = {
        method: 'GET',
        url: `https://stujo-tic-tac-toe-stujo-v1.p.rapidapi.com/${game}/X`,
        headers: {
        'X-RapidAPI-Key': #your api key,
        'X-RapidAPI-Host': #rapidapi host
        }
    };
    
    axios.request(options).then(function (response) {
        if (winner === 'No winner'){
            setboard(prevstate => ({...prevstate, [response.data.recommendation]: 'X'}))
            
        }
    }).catch(function (error) {
        console.error(error);
    });
        
    }, [undo])
```
If you look at the API documentation, you could see that we need to pass in the current state of the board in the URL.

![API documentation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ra29usssq6ghzphybjvz.png)

And that's it!! Did you enjoy the tutorial? Write your suggestions in the comment section.