Understanding the game concept
Tic-tac-toe game is a two-player game represented with "X" player one and "0" player two. The game board has 3 by 3 grid layout. The winner of the game plays repeated values of (X or 0) in each square vertically, horizontally or diagonally.
Using a pen and paper, this game is easily designed and played. However, we are making a web version of it. View the demo below and let's code this game!
Demo
React setup
To start the game setup. You would need to install NodeJS on your local machine. Once you've installed Node, you need to install create-react-app
to start a React environment. The command below both installs create-react-app
and also sets up the Tic-tac-toe-app
folder and all necessary files to start a new React project.
npx create-react-app Tic-tac-toe-app
This code syntax does not make sense to you right, let me break it down
npx
is a command that controls package handling node pack manager registry.
create-react-app
helps you set up pipeline packages for the applications with the latest ES6 features.
Tic-tac-toe-app is the project folder name. This folder houses all packages and code files needed for the project.
Check the output by writing this command.
npm run start
This runs a local server in your machine, and generate a link for output view, with a port number attached http://localhost:3000
Navigating through the folders and preparing the file
cd Tic-tac-toe-app
cd src
# on Windows:
del *
cd
command is to move into the tic-tac-toe-app
folder.
We deleted all *
files in the src
(source) folder.
Since we deleted all files, let's create new files in the src
folder
- Index.js file for script code in react js
- Index.css for styling code
Then navigate to the script file.
Import react library from react module in the package installed, same as the react virtual dom and the external styling sheet file in the source folder.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
Game code and lessons
React is structured with components, a component stores reusable pieces of code. Greatly, components interact with each other in a specific pattern, parent to child, through which resource sharing is possible.
Two types of react components will be discussed
- Functional-based component
- Class-based component
Functional-based component
A simple way to write react component is using the functional-based component because it is simply writing javascript functions. It can be used when a component has no interactivity with other components.
Class-based component
It is quite similar to other functional component but it allows complex features in react to be implemented example life cycle hooks, render method and passing of props which is the core of interaction among components.
Square component
function Square(props) {
return (
<div>
<button className="square" onClick={props.onClick}>
{props.value}
</button>
</div>
);
}
The function above is a Functional-based component and it does the following:
- Props which means property is passed as a parameter.
- The
props
is a JavaScript object. - The function returns a
div
, and abutton
embedded. - The button reacts to an event listener (
onClick
) attached to props - The
button
's value is passed in as a prop -props.value
.
Board component
class Board extends React.Component{
constructor(props){
super(props);
this.state ={
squares: Array(9).fill(null),
xIsNext: true,
}
}
handleClick(i) {
const squares = this.state.squares.slice();
if (calculateWinner(squares) || squares[i]) {
return;
}
squares[i]= this.state.xIsNext ? 'X' : 'O'
this.setState({
squares: squares,
xIsNext: !this.state.xIsNext,
});
}
renderSquare(i){
return <Square
value={this.state.squares[i]}
onClick={()=> this.handleClick(i)}
/>;
}
render() {
const gameName = "TIC TAC TOE"
const winner = calculateWinner(this.state.squares);
let status;
if (winner) {
status = 'Winner: ' + winner;
} else {
status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
}
return (
<div className="board">
<div className="gameName">{gameName}</div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
<div className="status">{status}</div>
<div className="btn">
<App/>
</div>
</div>
);
}
}
This class component named Square(function name).
Has 5 categories of actions
- The constructor category, calls a superclass constructor, initializing the state.
Defining squares and assigning them to 9 empty array spaces in the memory.
Defining xIsNext and assigning to true. - The handleclick method, controls the value for each square and on next click what value is to be assigned (X or 0), also with each click the winner can be calculated.
- Render square output square value on click. A child component square in Board component
- Render method for the board control the logic for the game-winner and the next player.
- Return for board output the title of the game, the grid, the status of the game, and a button for refreshing the whole game.
Game component
class Game extends React.Component {
render() {
return (
<div className="game">
<div className="game-board">
<Board />
</div>
</div>
)
}
}
- The above component is a class component.
- The render method displays the content as the main output on the localhost.
- It calls a child component board in it.
- The className is a styling selector in CSS for styling.
Creating the resulting logic and refresh functionality
Button component
function btnApp() {
function refreshPage() {
window.location.reload(false)
}
return (
<div>
<button className="refreshBtn" onClick={refreshPage}>
Refresh{" "}
</button>
</div>
)
}
- The
btnApp
function is a react function based component. - This function controls the refresh button
- The function
refreshPage
uses thewindow.location.reload
method to provide means to reload the page at current URL. - The return display the HTML output for the button, and styling on the class name
refreshBtn
and an add event listener (onclick) calls therefreshPage
function to refresh the game when clicked. -
The winner game logic
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
}
A 3 by 3 grid pattern is designed for the board right, each square is numbered between (0-8).
Remember, how a player wins the game. A player wins if a value fills in the squares diagonally, horizontally or vertically.
With the number grid(0-8). let's generate an instance of output for X or Y value
Horizontally: (0,1,2) (3,4,5)(6,7,8)
Vertically: (0,3,6)(0,4,7)(2,5,8)
Diagonally: (0,4,8)(2,4,6)
This square position on the board determines the output prediction of the game.
The function calculateWinner run all the possible output, return the result. The generate output is assigned to a nested array[[a,b,c]].
Looping to the array, to get an exact result of the game.
A condition is created.
Moves by player
square[a] = X
square[a]== square[b]
it means player played X in square b
square[a]== square[C]
and the same player played X in square C
It means three square positions are filled with X, so player x is the winner.
React dom call
ReactDOM.render(<Game />, document.getElementById("root"))
Conclusion
Style any of the className with the desired styling and achieve the same output.
A simple guide to developing a tic-tac-toe game.
Kindly use the comment section, if you have questions about this article.
Want to follow me on Twitter? @Bolarinwaajayi1