This game uses the basic technologies of HTML5, CSS3 and JavaScript. We’ll cover data properties, positioning, perspectives, transformations, flexbox, event handling, timeouts, and triples. You don’t need a lot of programming knowledge or experience to understand it, but you do need to know what HTML, CSS and JS are.

  • 🕹 Demo: the Memory Game Project [https://marina-ferreira.github.io/memory-game/] (click on the “original” at the bottom of the direct GayHub Project)

The project structure

Create project file in terminal:

HTML

Initialize the page template and link the CSS file to the JS file.

There are 12 cards in this game. Each card contains a container div named.memory-card, which contains two IMG elements. One represents the front face of the card and the other represents the back face.


You can download the resource file for this project at GitHub: Memory Game Repo [https://github.com/code-sketch/memory-game].

This set of cards will be wrapped in a section container element. The final code is as follows:

CSS

We’ll use a simple but very useful configuration and apply it to all projects:

Box-sizing: border-box allows the element to fill the entire border, so we don’t have to do any math.

Set display: flex to the body and apply margin: Auto to the.memory-game container to center the vertical horizontally.

Memory-game is an elastic container, and by default, the elements in it shrink to fit the container. By setting flex-wrap to wrap, it ADAPTS to the size of the elastic element.

The width and height of each card are calculated using the CSS calc() function. Now we need to create a screen with three rows and four columns, and set width to 25%, height to 33.333%, and subtract 10px for full margins.

To position the.memory-card child, we also add the attribute Position: relative, so that we can absolutely position the child relative to it.

Setting the position property of both front-faceand back-face to Absolute removes elements from their original positions and stacks them together.

The page template should look something like this:

We also need to add a click effect. The active pseudo-class fires every time an element is clicked, which causes a 0.2-second transition:

Flip CARDS

To flip the card when clicked, you need to add a flip class to the element. . Therefore, let us use the document querySelectorAll select all the memory card – element, then use the forEach traverse them and attach an event listener. Every time the card is clicked, the flipCard function is triggered, where this represents the clicked card. The function accesses the element’s classList and switches to the flip class:

The flip class in CSS rotates the card by 180deg:

To produce the 3D flip, you also need to add the perspective property to the.memory-game. This property sets the distance between the object and the user on the Z-axis. The smaller the value, the stronger the perspective. For best results, set it to 1000px:

Next, add the transform-style: preserve-3D attribute to the.memory-card element, which places the card in the 3D space created in the parent node instead of tiled on a z = 0 plane (transform-style).

Change the transition property to transform to generate dynamic effects:

Yeah! Now we have the card with the 3D flip effect, but why doesn’t the other side of the card appear? Because of absolute positioning,.front-face and.back-face are now stacked together. Each element’s back face is a mirror image of its front face. The property backface-visibility defaults to Visible, so when we flip the card, we get the JS badge on the back.

To display the image behind it, let’s add Backface-visibility: Hidden to.front-face and.back-face.

If we refresh the page and flip a card, it’s gone!

img

Since we hid both images on the back, there is nothing on the other side. So now we need to flip.front-face 180 degrees again:

The effect is finally here!

Match the CARDS

Now that you’ve done the flipping of the cards, you can process the matching logic.

When you click on the first card, you wait for the other card to be flipped. The hasFlippedCard and flippedCard variables are used to manage the flip state. If there is no card flip, hasFlippedCard is set to true and flippedCard is set to the card clicked. Let’s switch to the toggle method:

Now, when the user clicks on the second card, the code goes into the else block, and we’ll check to see if they match. To do this, you need to be able to identify each card.

Data attributes can be used whenever we want to add additional information to an HTML element. Data -*, where * can be any word, is inserted into the dataset property of the element by using the following syntax: data-*. So add a data-framework for each card:

Copy the code


Now you can check for matches by accessing the data sets of both cards. Now extract the matching logic to its own method checkForMatch() and set hasFlippedCard to false. If there isa match, call disableCards() and separate the event listeners on both cards to prevent another rollover. Otherwise unflipCards() will restore both cards to a timeout of more than 1500 milliseconds and delete the.flip class:

Put the code together:

A more elegant way to match a condition is to use the ternary operator, which consists of three parts: the first part is the condition to determine, and the second part of the code is executed if the condition fits, otherwise the third part is executed:

lock

Now that the matching logic is complete, you need to lock both sets of cards to avoid rotating them at the same time, or the flip will fail.

Declare a lockBoard variable. When the player clicks on the second card, the lockBoard is set to true with the condition if (lockBoard) return; Prevents other cards from flipping until they are hidden or matched:

Click on the same card

Still, the player can click twice on the same card. If the match condition is judged to be true, the event listener is removed from the card.

To prevent this, you need to check if the currently clicked card is equal to firstCard and return if it is positive.

The variables firstCard and secondCard need to be reset after each round, so let’s extract it into a new method, resetBoard(), with hasFlippedCard = false; And lockBoard = false. Es6’s destruct assignment function [var1, var2] = [‘value1’, ‘value2’] allows us to write extremely short code:

Then call the new methods disableCards() and unflipCards() :

Shuffle the deck

Our game looks pretty good, but it’s not fun if you can’t shuffle, so deal with this feature now.

When display: flex is declared on a container, flex-items are sorted by group and source order. Each group is defined by the Order attribute, which contains either positive or negative integers. By default, each Flex-Item has its order attribute set to 0, which means that they all belong to the same group and will be sorted by source. If there are multiple groups, they are sorted first in ascending group order.

There are 12 cards in the game, so we’ll iterate over them, generating random numbers between 0 and 12 and assigning them to the Flex-item order property:

To call the shuffle function, make it an immediate call function expression (IIFE), which means it will be executed immediately after the declaration. The script should look like this:

Finally done!

You can also find video demonstrations on YouTube: 🎬 Code Sketch Channel [https://www.youtube.com/watch?v=eMhiMsEC9Uk&list=PLLX1I3KXZ-YH-woTgiCfONMya39-Ty8qw].



This article is first published on the public account of Beijing Chengyi Lamp!!

㊗️