Memory Game
Solution
Step 1: Structure the HTML
Create a Container: Set up a container that will hold the game board. This container will be used to dynamically generate and display the cards.
Step 2: Style the Game with CSS
- Create a Grid Layout: Use CSS to style the game board as a grid with 4 rows and 4 columns. Define styles for the cards, including their size, background color, and how they should look when flipped.
- Implement 3D Flip Animation: Add CSS transitions to enable a smooth 3D flip effect when the cards are clicked. This will create the effect of the cards flipping over to reveal their hidden content.
Step 3: Implement the Game Logic with JavaScript
- Prepare the Card Data: Define an array of 8 unique letters (or symbols) and duplicate it to create pairs. Shuffle the array to randomize the card positions on the board.
- Generate the Cards Dynamically: Loop through the shuffled array and create card elements for each letter. Each card has two sides: a front (hidden) and a back (revealing the letter when flipped).
- Handle Card Click Events: Add an event listener to detect when a card is clicked. When a card is clicked, flip it to reveal its letter.
- Check for Matching Pairs: Track the first and second cards that are flipped. If the two cards match, leave them flipped and reset the tracking variables. If they do not match, wait a moment, then flip both cards back over and reset the tracking variables.
- Manage the Game Flow: Continue flipping cards and checking for matches until all pairs are found. Optionally, you could add a mechanism to track the number of attempts or the time taken to find all pairs.
Step 4: Test and Refine
- Test the Game: Test the game thoroughly to ensure that all pairs can be matched and that cards flip correctly. Ensure that the game resets correctly after a match or a non-match.

Pure HTML
/* styles.css */
body {
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
.controls {
margin-bottom: 20px;
}
.game-board {
display: grid;
grid-template-columns: repeat(4, 100px);
gap: 10px;
}
button {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
.card {
width: 100px;
height: 100px;
perspective: 1000px; /* Create a 3D space for card flip */
}
.card-inner {
width: 100%;
height: 100%;
transition: transform 0.6s;
transform-style: preserve-3d;
position: relative;
}
.card.flipped .card-inner {
transform: rotateY(
180deg
); /* Flip the card when it has the "flipped" class */
}
.card-front,
.card-back {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
backface-visibility: hidden;
display: flex;
justify-content: center;
align-items: center;
font-size: 36px;
border-radius: 8px;
}
.card-front {
background-color: #4caf50;
color: white;
}
.card-back {
background-color: #ffffff;
color: #4caf50;
transform: rotateY(180deg); /* Back of the card, initially hidden */
}
React JS
body {
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
.controls {
margin-bottom: 20px;
}
.game-board {
display: grid;
grid-template-columns: repeat(4, 100px);
gap: 10px;
}
button {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
.card {
width: 100px;
height: 100px;
perspective: 1000px; /* Create a 3D space for card flip */
}
.card-inner {
width: 100%;
height: 100%;
transition: transform 0.6s;
transform-style: preserve-3d;
position: relative;
}
.card.flipped .card-inner {
transform: rotateY(
180deg
); /* Flip the card when it has the "flipped" class */
}
.card-front,
.card-back {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
backface-visibility: hidden;
display: flex;
justify-content: center;
align-items: center;
font-size: 36px;
border-radius: 8px;
}
.card-front {
background-color: #4caf50;
color: white;
}
.card-back {
background-color: #ffffff;
color: #4caf50;
transform: rotateY(180deg); /* Back of the card, initially hidden */
}