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 3×3 grid. Additionally, it should also detect when someone has won the game or, in the alternative, if there is a tie.
Requirements
- First, handle user events; then, update 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 for React Tic Tac Toe
- 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 3×3 grid of squares, using buttons or other clickable elements to allow the user to place X‘s and O‘s on the board.
- Start by implementing logic to determine whether a player has won or if the game has ended in a tie. Then, display an appropriate message to inform the user accordingly.
- 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 diving into the final output, I encourage you to take some time to work through the exercise on your own. I believe that active learning is the most effective way to learn and grow as a developer.
Begin by grabbing a pen and paper. Next, open your code editor, and before you know it, you’ll be diving 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 applies CSS styles to the TicTacToe component. The game class centers the game board both vertically and horizontally on the page. The board class defines the styling for the game board itself, including border, padding, and margin. The row class is used to style the rows of squares on the board, while the square class targets individual squares. The status class styles the game status text located at the top of the board, and the reset class applies styles to 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!
Boost your React skills with 25 React JavaScript Practice Exercises with Solutions hands-on challenges to master components, hooks, and more!