Build a Card Memory Game with React

Shubham Khatri
JavaScript in Plain English
4 min readApr 3, 2021

--

Very often we come across small games and wonder how complex is it? Can we build it? More often than not we do not go beyond it. In this post however we will build a simple memory game which is easy to play and also easy to develop.

The card memory game is a simple game to test the player’s memory. In a deck of paired cards, the player needs to select a matching pair in consecutive turns. The player wins the game when all matching pairs are selected.

A simple UI of it may look like this:

Let us define the Rules of the Game

We can’t make a game unless we know the rules. So lets state them here:

  • We need a shuffled set of cards. There must be a pair of each card in our deck.
  • The game must flip the cards clicked by the player. Maximum of two cards will show at a time.
  • The game will handle matched and unmatched cards. Unmatched cards are flipped back after a short duration. Matched cards are removed from the deck.
  • Every time a player selects a pair, the game will increment the current move count
  • Once all pairs are found out, players sees a confirmation dialog with the score.
  • Game provides a functionality to restart.

So what are we waiting for... Lets get into it.

We first define our card structure. For a card we create an object with the type attribute and an image source.

{
type: 'Pickachu',
image: require('../images/Pickachu.png')
}

Now the next step is to shuffle the deck of cards. Ahh yes, this is the most important step. It is not really a memory game if we don’t shuffle

1. Shuffle

I will use Fisher-Yates shuffle algorithm for shuffling an array of cards but we can use any algorithm or code that gives us a randomized array.

Fisher Yates shuffle algorithm to shuffle our card deck

2. Render board for the deck of cards

In this example, we are using 12 cards(6 pairs). After shuffling our cards, we render them as a grid of 3x4. You can either choose to split your card deck into 3 arrays of 4 items each and render using a nested map or use CSS flexbox or grid. I will be using CSS Grid to render it since it is easier to handle updates with a one-dimension array.

Layout Component
Grid container CSS

3. Flip Cards, evaluate match and count moves

The next step is to provide an interaction for the user to flip cards and evaluate if there is a match. For it, we maintain the following states

  • openCards to track the cards that have been flipped by the player
  • clearedCards to track the cards that have matched and need to be removed from the deck
  • moves to keep track of the moves made by the player.
Handling Flip and evaluate

At a time we shall only keep a maximum of two cards in openCards state. Since we have a static array and we aren’t actually deleting anything from our original cards array we can just store the index of the opened card in openCards state. Based on openCards and clearedCards state we pass a prop isFlipped or isInactive respectively to our Card component which it will then use to add the respective class.

Do look at this wonderful blog which explains how to handle Flip Card Animation.

Note: Since we add an animation to our cards for flipping, we evaluate a match after few seconds to allow for the flip transition.

4. Check for game completion

Every time we evaluate for a match, we check if all pairs have been found. If yes, we show the player a completion modal.

5. And finally, our restart functionality

Well, restarting is simple, we just reset our states and reshuffle our cards.

Hurray! There we have our basic memory card game.

Codesandbox playground

Conclusion

I am so glad we’ve reached this point. We created a shuffled deck, rendered it on a board, added a flip functionality, and evaluated it for a matching pair. We can extend this example to add a timer, add the best score of the player, and support level for higher numbers of cards as well.

You can check this Github repository for the full code.

More content at plainenglish.io

--

--

Software Engineer at Meta | Passionate about Javascript, React and Web Development | Active Stackoverflow contributor