Shuffle the Cards

Learn to use the spread and random methods to shuffle the cards.

In the shuffleCard function, we shuffle our CardImages in a random order and use the button in the Header component to create a new game any time a user clicks it. To define the shuffleCard function, we use CardImages, which is a collection of flags from various countries that have already been passed for us to use in the App.js component. We use the spread operator two times to create the array of image pairs. This is because we need to select two similar images. We use JavaScript’s Math.random() method because we want the images to be placed in random order.

Define the shuffleCard function

Let’s start by importing the useState and useEffect hooks to handle our state of shuffled-card order and turns, which is the number of turns the user took to guess the correct pair of images. The useEffect hook calls the shuffleCard function on each render of the component. The following snippet shows how to define the function:

const [cards, setCards] = useState([]);
const [turns, setTurns] = useState(0);

const shuffleCard = () => {
  const shuffledCards = [...cardImages, ...cardImages]
    .sort(() => Math.random() - 0.5)
    .map((card) => ({ ...card, id: Math.random() }));

  setCards(shuffledCards);
  setTurns(0);
};

We create the shuffleCards variable in the snippet above, which holds an array of images that we randomly sort using the Math.random() function. which generates negative and positive values at random. The sort method takes the array of images, compares all of the images with each other to see if they are a pair, and then either swaps the two or leaves them as is. To determine whether the cards should be swapped, we pass the Math.random() function as an argument to the sort method. If the Math.random() function returns a negative value, the two images being compared are swapped. If no two images in the array are swapped, the array will remain in its original form.

To get a random permutation of the image array, we want some values to be swapped—specifically, for this application, we want to swap the images 50 percent of the time. So, we need the value returned by the Math.random() argument to sort to be positive 50% of the time, and negative 50% of the time. Because Math.random() returns a random value between 0 and 1, subtracting 0.5 from the value means that the random result Math.random() returns will always be between -0.5 and 0.5. This gives us a 50% probability of the value being positive, and a 50% probability of it being negative—which is our goal to randomly sort our cards. We then map over the randomly sorted array and return the object with the card variable that we defined in the Export Images lesson. It holds the src and matched properties. At the end, we use the setCards state updating function to update the array with the 12 random images and set the value of turns to 0 on every new game by using setTurns.

Use the useEffect hook

Because we want the card to reshuffle on the game’s first render, we use the useEffect method to execute our shuffleCard function on the first render.

// Call the shuffle card function
useEffect(() => {
  shuffleCard();
}, []);

Get hands-on with 1200+ tech skills courses.