Skip to main content

Create a Memory Matching Game with HTML, CSS, and JavaScript - Step-by-Step Guide

Creating a Memory Game using HTML, CSS, and JavaScript is a fun project that allows you to practice both your front-end and logic skills. Here's a step-by-step guide to building the game:

Step 1: HTML Structure

We need to create a grid of cards, each of which has hidden content. Let's create the basic structure for our memory game:

html
<!DOCTYPE html>
<html lang="en"> 
<head> 
<meta charset="UTF-8"> 
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Memory Game</title> 
<link rel="stylesheet" href="style.css"> 
</head>
<body> 
<div class="game-container"> 
<div class="game-board" id="game-board">
<!-- Cards will be generated here -->
</div> <div class="info"> 
<p>Moves: <span id="move-count">0</span></p> 
<p>Time: <span id="timer">00:00</span></p>
</div> 
</div> 
<script src="script.js">
</script> 
</body> 
</html>

Step 2: CSS Styling (style.css)

Now, we'll style the cards and the board. The cards should flip when clicked, and we'll also make the board responsive.

css
* { 
margin: 0; padding: 0; box-sizing: border-box; 
} body {
font-family: Arial, sans-serif; background-color: #f5f5f5; display: flex; justify-content: center; align-items: center; min-height: 100vh; } 
.game-container { text-align: center; } 
.game-board { display: grid; grid-template-columns: repeat(4, 100px); /* Adjust for more cards */ gap: 10px; margin-bottom: 20px; } 
.card { width: 100px;
height: 100px;
background-color: #3498db;
border-radius: 8px; display: flex;
justify-content: center; 
align-items: center;
font-size: 20px
color: white;
cursor: pointer;
position: relative; 
transform-style: preserve-3d;
transition: transform 0.5s;
 } 
.card.flipped { transform: rotateY(180deg);
 } 
.card .card-content { position: absolute;
backface-visibility: hidden;
 } 
.card .card-back { transform: rotateY(180deg);
background-color: #2980b9; } 
.info p { font-size: 18px;
margin: 10px 0;
 } @media (max-width: 600px) { 
.game-board { grid-template-columns: repeat(3, 100px);
 } }

Step 3: JavaScript Game Logic (script.js)

Now comes the fun part — implementing the game logic! The following JavaScript will handle card flipping, checking for matches, updating the number of moves, and tracking the time.

javascript
const cardValues = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'];
let cards = [...cardValues, ...cardValues]; 
// Duplicate to create pairs 
let flippedCards = []; 
let matchedCards = []; 
let moveCount = 0
let timerInterval; 
let seconds = 0;
function shuffleCards(cards) { return cards.sort(() => Math.random() - 0.5); }
function startTimer() { timerInterval = setInterval(() => { seconds++; document.getElementById('timer').textContent = formatTime(seconds); }, 1000); }
function formatTime(seconds) { const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60
return `${String(minutes).padStart(2, '0')}:${String(remainingSeconds).padStart(2, '0')}`; } 
function createCardElements() { 
const gameBoard = document.getElementById('game-board'); 
const shuffledCards = shuffleCards(cards); shuffledCards.forEach(value =>
const card = document.createElement('div'); card.classList.add('card'); 
const front = document.createElement('div'); front.classList.add('card-content'); front.textContent = ''
// Hidden content on the front 
const back = document.createElement('div'); back.classList.add('card-content', 'card-back');
 back.textContent = value; card.append(front, back); gameBoard.appendChild(card); 
 card.addEventListener('click', () => flipCard(card)); }); } 
function flipCard(card) { 
if (flippedCards.length === 2 || card.classList.contains('flipped')) return; card.classList.add('flipped');
 flippedCards.push(card); 
if (flippedCards.length === 2) { checkForMatch(); } } function checkForMatch() {
const [card1, card2] = flippedCards; 
const value1 = card1.querySelector('.card-back').textContent
const value2 = card2.querySelector('.card-back').textContent
if (value1 === value2) { matchedCards.push(card1, card2); flippedCards = []; updateMoveCount(); 
if (matchedCards.length === cards.length) { endGame(); } } 
else { setTimeout(() => { card1.classList.remove('flipped'); card2.classList.remove('flipped'); flippedCards = []; updateMoveCount(); }, 1000); } } 
function updateMoveCount() { moveCount++; document.getElementById('move-count').textContent = moveCount; } 
function endGame() { clearInterval(timerInterval); 
alert('Congratulations! You won the game.'); } 
function initializeGame() { createCardElements(); startTimer(); } initializeGame();

Explanation of Key Parts:

  • HTML: We set up the structure for the game container, game board, and a section to display the number of moves and the timer.
  • CSS: The cards are styled with a flip effect using CSS transformations. The flipped class rotates the card 180 degrees to show the back. The layout is responsive using grid layout, and we adjust the number of columns based on the screen size.
  • JavaScript:
    • Game Logic: Cards are shuffled and displayed. When clicked, cards flip and reveal the value. If two cards match, they remain flipped; if not, they flip back after a short delay.
    • Timer: The timer runs from the moment the game starts and tracks time.
    • Moves Counter: Every time a pair is revealed (whether they match or not), the move count increments.
    • End Game: When all cards are matched, the game ends and an alert is shown with the victory message.

Output




Optional Enhancements:

  • Add a "Restart" button to start a new game.
  • Include more levels with varying grid sizes (e.g., 4x4, 6x6).
  • Add sound effects when cards are flipped or when a match is made.
  • Add difficulty levels where you can change the number of cards.