Overview
Create a simple tic-tac-toe game using React. The goal will be to create a user interface that allows two players to take turns placing X's and O's on a 3x3 grid and to detect when someone has won the game or if there is a tie.
Requirements
Handling user events and updating the state accordingly
Conditional rendering to display different UI elements based on the game state
Checking for a win or draw conditions in the game board
Implementing a reset button to start a new game
Instructions
Implement a component for the tic-tac-toe game, with appropriate state management to keep track of the game board and current player.
Render the game board as a 3x3 grid of squares, using buttons or other clickable elements to allow the user to place X's and O's on the board.
Implement logic to detect when a player has won or if there is a tie, and display an appropriate message to the user.
Include a reset button that allows the user to start a new game.
Apply appropriate styling and layout to create a visually appealing user interface.
Test your game to ensure that it is working correctly and meets the requirements.
Before you dive into the final output, I want to encourage you to take some time to work through the exercise yourself. I believe that active learning is the most effective way to learn and grow as a developer.
So, grab a pen and paper, fire up your code editor, and get ready to dive into the React Tic Tac Toe exercise. Once you have completed the exercise, feel free to return to this blog post to compare your solution to mine.
Output for the Tic Tac Toe exercise
import React, { useState } from 'react';
function TicTacToe() {
const [board, setBoard] = useState(Array(9).fill(null));
const [xIsNext, setXIsNext] = useState(true);
function handleClick(index) {
const squares = [...board];
if (squares[index] || calculateWinner(squares)) {
return;
}
squares[index] = xIsNext ? 'X' : 'O';
setBoard(squares);
setXIsNext(!xIsNext);
}
function renderSquare(index) {
return (
<button className="square" onClick={() => handleClick(index)}>
{board[index]}
</button>
);
}
const winner = calculateWinner(board);
const status = winner
? `Winner: ${winner}`
: `Next player: ${xIsNext ? 'X' : 'O'}`;
return (
<div className="game">
<div className="board">
<div className="status">{status}</div>
<div className="row">
{renderSquare(0)}
{renderSquare(1)}
{renderSquare(2)}
</div>
<div className="row">
{renderSquare(3)}
{renderSquare(4)}
{renderSquare(5)}
</div>
<div className="row">
{renderSquare(6)}
{renderSquare(7)}
{renderSquare(8)}
</div>
</div>
<button className="reset" onClick={() => setBoard(Array(9).fill(null))}>
Reset
</button>
</div>
);
}
function calculateWinner(squares) {
const lines = [ [0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
export default TicTacToe;
This code creates a TicTacToe
component that maintains the game state using the useState
hook. The handleClick
function is used to update the board state and check for win conditions. The renderSquare
function renders each square on the board as a button and the calculateWinner
function determines if there is a winner based on the current board state. The status
variable is used to display the current game status to the user. Finally, a reset
button is included to allow the user to start a new game.
.game {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
height: 100vh;
}
.board {
display: flex;
flex-direction: column;
align-items: center;
border: 2px solid black;
padding: 10px;
margin-right: 20px;
}
.row {
display: flex;
}
.square {
width: 80px;
height: 80px;
font-size: 48px;
border: 2px solid black;
margin-right: -2px;
margin-bottom: -2px;
display: flex;
justify-content: center;
align-items: center;
background-color: #fff;
cursor: pointer;
}
.square:hover {
background-color: #f0f0f0;
}
.status {
font-size: 24px;
font-weight: bold;
margin-bottom: 10px;
}
.reset {
font-size: 24px;
font-weight: bold;
padding: 10px 20px;
border: 2px solid black;
background-color: #fff;
cursor: pointer;
}
.reset:hover {
background-color: #f0f0f0;
}
This code styles the TicTacToe
component using CSS. The game
class is used to center the game board vertically and horizontally on the page. The board
class styles the game board itself, with a border, padding, and margin. The row
class styles the rows of squares on the board, and the square
class styles the individual squares. The status
class styles the game status text at the top of the board, and the reset
class styles the reset button at the bottom of the board.
Thanks for taking this JavaScript exercise!
By building this game, you've gained valuable experience working with React components, props, state, and events. You've also had the opportunity to practice debugging and troubleshooting issues that arise during development.
Remember that there are many ways to approach the design and implementation of a React game like this one, and you can always customize and extend the functionality to create your unique version. The possibilities are endless!
I hope you found this exercise helpful and enjoyable, and that it has deepened your understanding of React development. Keep practising and experimenting with React, and you'll be well on your way to becoming a skilled React developer!
If you have any questions or comments, feel free to reach out to me on Twitter(@rajeshtomjoe), or follow me for more updates.
And if you'd like to receive more exercise on JavaScript, be sure to subscribe to my blog.