In this article, we will create a Memory game using ReactJS. A memory game is a famous game in which a pair of cards are placed in front of a player with their face down. The two pairs are always going to have the same content. The player has the choice to select any two cards at a time and check if the faces of the card match or not. If the face content match then he can keep the images with their face up and continue else the players needs to put them back face down. The game is over when all the pairs have been matched.
Preview of Final Output:
 Memory Game Using React
Technologies Used:
Pre-requisites
Approach:
As most of the logic is contained by the GameBoard.js component we will mainly focus on it and break the logic in steps but first Import GameBoard.js into App.js and render it there as App.js is the parent component for the GameBoard.js. Inside the GamBoard functional Component, we will create another function named NewGame() which restarts the whole game by suffling the cards and resetting the other variables. This function will only be executed when the new game button is clicked. Now to handle the clicks on the image card we create a new function called handleSelectedCards() which will simply check which card is selected and store its value in the firstCard and secondCard variables for further checking.
Steps to create the project:
Step 1 : Choose a particular IDE of your choice (preferably VS Code) .
Step 2: Create React Project Folder by using the below commands.
npx create-react-app <<projectname>>
Step 3: Navigate to the project folder.
cd <<projectname>>
Step 4: Create a folder “Game” and add five new files GameBoard.js, Card.js, and Data.js.
Project Structure:
 Project Structure Example: Write the following code in respective files:
- App.js:This file imports the GameBoard component and renders it.
- GameBoard.js: This file contains most of the logic from creation of individual cards to handling the various function calls and representing the cards in specific order.
- Card.js: This file contains the code to generate individual cards.
- Data.js:This file contains an array which has data regarding the images like image source, name and individual address it gets imported by GameBoard.js.
- App.css: This file contains the design for every component.
Javascript
import "./App.css" ;
import GameBoard from "./Game/GameBoard" ;
function App() {
return (
<div className= "App" >
<GameBoard />
</div>
);
}
export default App;
|
Javascript
import React from "react" ;
import Data from "./data" ;
import Card from "./Card" ;
function GameBoard() {
const [cardsArray, setCardsArray] = React.useState([]);
const [moves, setMoves] = React.useState(0);
const [firstCard, setFirstCard] = React.useState( null );
const [secondCard, setSecondCard] = React.useState( null );
const [stopFlip, setStopFlip] = React.useState( false );
const [won, setWon] = React.useState(0);
function NewGame() {
setTimeout(() => {
const randomOrderArray = Data.sort(() => 0.5 - Math.random());
setCardsArray(randomOrderArray);
setMoves(0);
setFirstCard( null );
setSecondCard( null );
setWon(0);
}, 1200);
}
function handleSelectedCards(item) {
console.log( typeof item);
if (firstCard !== null && firstCard.id !== item.id) {
setSecondCard(item);
} else {
setFirstCard(item);
}
}
React.useEffect(() => {
if (firstCard && secondCard) {
setStopFlip( true );
if (firstCard.name === secondCard.name) {
setCardsArray((prevArray) => {
return prevArray.map((unit) => {
if (unit.name === firstCard.name) {
return { ...unit, matched: true };
} else {
return unit;
}
});
});
setWon((preVal) => preVal + 1);
removeSelection();
} else {
setTimeout(() => {
removeSelection();
}, 1000);
}
}
}, [firstCard, secondCard]);
function removeSelection() {
setFirstCard( null );
setSecondCard( null );
setStopFlip( false );
setMoves((prevValue) => prevValue + 1);
}
React.useEffect(() => {
NewGame();
}, []);
return (
<div className= "container" >
<div className= "header" >
<h1>Memory Game</h1>
</div>
<div className= "board" >
{
cardsArray.map((item) => (
<Card
item={item}
key={item.id}
handleSelectedCards={handleSelectedCards}
toggled={
item === firstCard ||
item === secondCard ||
item.matched === true
}
stopflip={stopFlip}
/>
))
}
</div>
{won !== 6 ? (
<div className= "comments" >Moves : {moves}</div>
) : (
<div className= "comments" >
???????? You Won in {moves} moves ????????
</div>
)}
<button className= "button" onClick={NewGame}>
New Game
</button>
</div>
);
}
export default GameBoard;
|
Javascript
function Card({ item, handleSelectedCards, toggled, stopflip }) {
return (
<div className= "item" >
<div className={toggled ? "toggled" : "" }>
<img className= "face" src={item.img} alt= "face" />
<div
className= "back"
onClick={() => !stopflip && handleSelectedCards(item)}
>
{ " " }
</div>
</div>
</div>
);
}
export default Card;
|
Javascript
const Data = [
{
id: 1,
name: "react" ,
img:
matched: false ,
},
{
id: 2,
name: "java" ,
img:
matched: false ,
},
{
id: 3,
name: "css" ,
img:
matched: false ,
},
{
id: 4,
name: "node" ,
img:
matched: false ,
},
{
id: 5,
name: "html" ,
img:
matched: false ,
},
{
id: 6,
name: "js" ,
img:
matched: false ,
},
{
id: 7,
name: "react" ,
img:
matched: false ,
},
{
id: 8,
name: "java" ,
img:
matched: false ,
},
{
id: 9,
name: "css" ,
img:
matched: false ,
},
{
id: 10,
name: "node" ,
img:
matched: false ,
},
{
id: 11,
name: "html" ,
img:
matched: false ,
},
{
id: 12,
name: "js" ,
img:
matched: false ,
},
];
export default Data;
|
CSS
* {
margin : 0 ;
padding : 0 ;
box-sizing: border-box;
}
.App {
height : 100 vh;
width : 100 vw;
font-family : cursive ;
background-color : rgb ( 21 , 56 , 66 );
}
.container {
display : flex;
flex- direction : column;
}
.header {
display : flex;
flex- direction : row;
padding : 10px ;
display : flex;
justify- content : center ;
align-items: center ;
}
h 1 {
align-self: start;
font-size : 2.5 rem;
color : rgb ( 247 , 247 , 247 );
}
.button {
display : flex;
align-items: center ;
justify- content : center ;
padding : 0.5 rem 0.8 rem;
font-family : cursive ;
width : 200px ;
font-size : 1.2 rem;
font-weight : bolder ;
border-radius: 0.7 rem;
border-style : none ;
background-color : red ;
color : white ;
margin-top : 4px ;
margin-left : 55% ;
}
.button:hover {
border : 2px solid black ;
cursor : pointer ;
}
.board {
display : grid;
margin : auto ;
margin-top : 3 rem;
grid-template-columns: repeat ( 4 , 9 rem);
place-items: center ;
row-gap: 2 rem;
}
.comments {
padding : 0.25 rem 1 rem;
background-color : white ;
margin : auto ;
margin-top : 40px ;
text-align : center ;
border-radius: 2 rem;
}
.face {
height : 6 rem;
}
.back {
height : 6 rem;
width : 6 rem;
background-color : rgb ( 253 , 218 , 175 );
color : rgb ( 61 , 21 , 21 );
border : 1px solid black ;
border-radius: 50% ;
}
.item .face {
position : absolute ;
transform: rotateY( 90 deg);
transition: all ease-in 0.25 s;
}
.toggled .face {
transform: rotateY( 0 deg);
transition-delay: 0.25 s;
}
.item .back {
transition: all ease-in 0.25 s;
transition-delay: 0.25 s;
}
.toggled .back {
transform: rotateY( 90 deg);
transition-delay: 0 s;
}
|
Steps to run the application:
Step 1: Type the following command in the terminal.
npm start
Step 2: Open web browser and type the following URL.
http://localhost:3000/
Output:
 GIF output of memory game
|