Free Memory Card Game Source Code in HTML, CSS & JavaScript

Get free Memory Card Game source code built with HTML, CSS and JavaScript. Learn how to create, customize and run a responsive HTML5 memory game.

It is a useful project for beginners who want to learn JavaScript arrays, click events, matching logic, game states, and basic animations.

Game Code and Features

  • Modern memory card design
  • Matching card gameplay
  • Move counter
  • Automatic win detection
  • Restart button
  • Responsive layout
  • No external libraries
  • Easy to customize
  • Works in modern browsers

How to Use the Game

Step 1: Create an HTML File

Create a new file named:

index.html

Step 2: Add the Code

Copy the complete code below into your index.html file.

Step 3: Open in Your Browser

Save the file and open it with Chrome, Edge, Firefox, or another modern browser.

Your Memory Card Game will start automatically.

Complete Memory Card Game Source Code

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Memory Card Game</title>

<style>
    * {
        box-sizing: border-box;
    }

    body {
        margin: 0;
        min-height: 100vh;
        display: flex;
        justify-content: center;
        align-items: center;
        background: #111827;
        font-family: Arial, sans-serif;
        color: white;
    }

    .game-container {
        width: 100%;
        max-width: 500px;
        padding: 20px;
        text-align: center;
    }

    h1 {
        margin-bottom: 8px;
    }

    .info {
        margin-bottom: 18px;
        color: #d1d5db;
        font-size: 17px;
    }

    .game-board {
        display: grid;
        grid-template-columns: repeat(4, 1fr);
        gap: 10px;
        max-width: 420px;
        margin: auto;
    }

    .card {
        aspect-ratio: 1;
        border: none;
        border-radius: 10px;
        background: #2563eb;
        color: white;
        font-size: 32px;
        cursor: pointer;
        transition: transform 0.2s, background 0.2s;
    }

    .card:hover {
        transform: scale(1.03);
    }

    .card.flipped,
    .card.matched {
        background: #1f2937;
    }

    .card.matched {
        background: #16a34a;
        cursor: default;
    }

    .restart {
        margin-top: 20px;
        padding: 11px 24px;
        border: none;
        border-radius: 7px;
        background: #7c3aed;
        color: white;
        font-size: 16px;
        cursor: pointer;
    }

    .restart:hover {
        background: #6d28d9;
    }

    @media (max-width: 480px) {
        .game-board {
            gap: 7px;
        }

        .card {
            font-size: 25px;
        }
    }
</style>
</head>

<body>

<div class="game-container">

    <h1>Memory Card Game</h1>

    <div class="info">
        Moves: <span id="moves">0</span>
    </div>

    <div class="game-board" id="gameBoard"></div>

    <button class="restart" onclick="startGame()">
        Restart Game
    </button>

</div>

<script>
const gameBoard = document.getElementById("gameBoard");
const movesDisplay = document.getElementById("moves");

const symbols = [
    "🍎", "🍎",
    "🚀", "🚀",
    "🎮", "🎮",
    "⚽", "⚽",
    "🌟", "🌟",
    "🎵", "🎵",
    "🔥", "🔥",
    "💎", "💎"
];

let firstCard = null;
let secondCard = null;
let lockBoard = false;
let moves = 0;
let matchedPairs = 0;

function shuffle(array) {
    return array.sort(() => Math.random() - 0.5);
}

function startGame() {

    gameBoard.innerHTML = "";

    firstCard = null;
    secondCard = null;
    lockBoard = false;
    moves = 0;
    matchedPairs = 0;

    movesDisplay.textContent = moves;

    const shuffledSymbols = shuffle([...symbols]);

    shuffledSymbols.forEach(symbol => {

        const card = document.createElement("button");

        card.classList.add("card");

        card.dataset.symbol = symbol;

        card.textContent = "?";

        card.addEventListener("click", flipCard);

        gameBoard.appendChild(card);
    });
}

function flipCard() {

    if (
        lockBoard ||
        this === firstCard ||
        this.classList.contains("matched")
    ) {
        return;
    }

    this.classList.add("flipped");
    this.textContent = this.dataset.symbol;

    if (!firstCard) {
        firstCard = this;
        return;
    }

    secondCard = this;

    moves++;
    movesDisplay.textContent = moves;

    checkMatch();
}

function checkMatch() {

    const isMatch =
        firstCard.dataset.symbol === secondCard.dataset.symbol;

    if (isMatch) {
        disableMatchedCards();
    } else {
        unflipCards();
    }
}

function disableMatchedCards() {

    firstCard.classList.add("matched");
    secondCard.classList.add("matched");

    matchedPairs++;

    resetTurn();

    if (matchedPairs === symbols.length / 2) {

        setTimeout(() => {
            alert(
                "Congratulations! You completed the game in " +
                moves +
                " moves."
            );
        }, 300);
    }
}

function unflipCards() {

    lockBoard = true;

    setTimeout(() => {

        firstCard.classList.remove("flipped");
        secondCard.classList.remove("flipped");

        firstCard.textContent = "?";
        secondCard.textContent = "?";

        resetTurn();

    }, 800);
}

function resetTurn() {

    firstCard = null;
    secondCard = null;
    lockBoard = false;
}

startGame();
</script>

</body>
</html>

How the Memory Game Works

The game contains pairs of hidden cards. When a player clicks a card, its symbol is revealed.

The player then selects another card. If both cards contain the same symbol, they remain open. If they do not match, the cards are hidden again after a short delay.

The game continues until all pairs have been matched.

Game Features Explained

Matching System

JavaScript compares the symbols stored in the two selected cards. If they are identical, the cards are marked as matched.

Move Counter

Every time the player selects two cards, the move counter increases.

Shuffle

The cards are randomly shuffled every time the game starts, so the layout changes after each restart.

Win Detection

When all card pairs have been matched, the game displays a congratulations message showing the number of moves used.