How To Create Memory Cards Game in JavaScript
In this Javascript Tutorial we will see How to Create a memory card game using JavaScript with HTML and CSS.
Players flip cards to find matching pairs, racing against time across three increasingly challenging levels.
The Game Features:
- Progressive Difficulty: Three levels with increasing complexity (6, 8, and 10 pairs).
- Time Pressure: Each level has a specific time limit to add urgency.
- Move Tracking: Monitors player efficiency with a move counter.
What We Are Gonna Use In This Project:
- Javascript Programming Language.- HTML and CSS.
- Visual Studio Editor.
- Visual Studio Editor.
Project Source Code:
- Card Flipping.
/**
* Handles flipping a card when clicked
* This function is called when a card is clicked
*/
function flipCard() {
// Check if this card can be flipped:
// - Less than 2 cards already flipped
// - This card is not already flipped
// - This card is not already matched
if (flippedCards.length < 2 && !this.classList.contains('flipped') &&
!this.classList.contains('matched')) {
// Add the 'flipped' class for styling
this.classList.add('flipped');
// Show the card's icon instead of the question mark
this.innerHTML = `<i class="fas ${this.dataset.icon}"></i>`;
// Add this card to the flipped cards array
flippedCards.push(this);
// If we now have 2 flipped cards, check if they match
if (flippedCards.length === 2) {
// Increment moves counter
moves++;
// Update the moves display
movesDisplay.textContent = moves;
// Wait half a second before checking if cards match
setTimeout(checkMatch, 500);
}
}
}
- Randomization Algorithm.
/**
* Shuffles an array using the Fisher-Yates algorithm
* @param {Array} array - The array to shuffle
*/
function shuffleArray(array) {
// Loop through the array backwards
for (let i = array.length - 1; i > 0; i--) {
// Pick a random index from 0 to i
const j = Math.floor(Math.random() * (i + 1));
// Swap elements at indices i and j using array destructuring
[array[i], array[j]] = [array[j], array[i]];
}
}
- Timer Implementation.
/**
* Updates the game timer
* Called every second by the timer interval
*/
function updateTime() {
// Increment the time elapsed in seconds
timeElapsed++;
// Format the time as MM:SS (with leading zeros)
const minutes = Math.floor(timeElapsed / 60).toString().padStart(2, '0');
const seconds = (timeElapsed % 60).toString().padStart(2, '0');
// Update the time display
timeDisplay.textContent = `${minutes}:${seconds}`;
// Check if time limit for the current level has been reached
if (timeElapsed >= difficulties[level].timeLimit) {
// Stop the timer
clearInterval(timerId);
// Show the time's up modal
showTimeUpModal();
}
}
- Creates a card element with a hidden icon.
/**
* @param {string} icon - The Font Awesome icon class
* @returns {HTMLElement} - The created card element
*/
function createCard(icon) {
// Create a new div element for the card
const card = document.createElement('div');
// Add the 'card' class for styling
card.classList.add('card');
// Set the initial content to show a question mark
card.innerHTML = `<i class="fas fa-question"></i>`;
// Store the icon class in a data attribute for later use
card.dataset.icon = icon;
// Add click event listener to handle card flipping
card.addEventListener('click', flipCard);
// Return the created card element
return card;
}
- Checks if two flipped cards match.
/**
* Checks if two flipped cards match
* Called after two cards are flipped
*/
function checkMatch() {
// Get the two flipped cards using array destructuring
const [card1, card2] = flippedCards;
// Check if the icons on both cards match
if (card1.dataset.icon === card2.dataset.icon) {
// If they match, increment the matched pairs counter
matchedPairs++;
// Add 'matched' class to both cards for styling
card1.classList.add('matched');
card2.classList.add('matched');
// Check if all pairs for this level are matched
if (matchedPairs === difficulties[level].pairs) {
// If all pairs are matched, stop the timer
clearInterval(timerId);
// Show the level complete modal after a brief delay
setTimeout(showLevelCompleteModal, 500);
}
} else{
setTimeout(() => {
// Remove the 'flipped' class
card1.classList.remove('flipped');
card2.classList.remove('flipped');
// Set the content back to the question mark
card1.innerHTML = `<i class="fas fa-question"></i>`;
card2.innerHTML = `<i class="fas fa-question"></i>`;
}, 1000);
}
// Reset the flipped cards array for the next turn
flippedCards = [];
}
- Displays the time's up notification modal.
/**
* Shows a time's up modal when the time limit is reached
*/
function showTimeUpModal() {
// Display the time's up modal
timeUpModal.style.display = 'flex';
}
- Displays level completion celebration with player statistics
/**
* Shows the level completion modal with stats
* Called when all pairs in a level are matched
*/
function showLevelCompleteModal() {
// Update level completion information
document.getElementById('completedLevel').textContent = level;
document.getElementById('completionTime').textContent = timeDisplay.textContent;
document.getElementById('completionMoves').textContent = moves;
// Display the level complete modal
levelCompleteModal.style.display = 'block';
}
- Advances the game to the next difficulty level or completes the game.
/**
* Advances to the next level
* Called when the next level button is clicked
*/
function nextLevel() {
// Increment the level
level++;
// Check if this was the final level
if (level > 3) {
// If so, show game completed modal and reset to level 1
level = 1;
// Hide the level complete modal
levelCompleteModal.style.display = 'none';
// Show the game completed modal
showGameCompletedModal();
}
else{
// Start a new game with the updated level
startGame();
// Hide the level complete modal
levelCompleteModal.style.display = 'none';
}
}
- Resets the entire game back to level 1 after completion.
/**
* Resets the game to level 1 after completing all levels
*/
function playAgain() {
// Reset to level 1
level = 1;
// Start a new game
startGame();
// Hide the game completed modal
gameCompletedModal.style.display = 'none';
}
- Displays the final celebration modal.
/**
* Shows the game completed modal with animations
*/
function showGameCompletedModal() {
// Display the game completed modal
gameCompletedModal.style.display = 'flex';
}
- Initializes or resets the game state and creates a new game board.
/**
* Starts or restarts the game
* Resets the game state and creates a new game board
*/
function startGame() {
// Reset game board and game state
gameBoard.innerHTML = ''; // Clear the game board
flippedCards = []; // Reset flipped cards array
matchedPairs = 0; // Reset matched pairs counter
moves = 0; // Reset moves counter
timeElapsed = 0; // Reset time elapsed
// Reset UI displays
movesDisplay.textContent = '0'; // Reset moves display
timeDisplay.textContent = '00:00'; // Reset time display
levelDisplay.textContent = level; // Update level display
// Hide any open modals
timeUpModal.style.display = 'none';
levelCompleteModal.style.display = 'none';
gameCompletedModal.style.display = 'none';
// Reset and start the game timer
clearInterval(timerId); // Clear any existing timer
timerId = setInterval(updateTime, 1000); // Start a new timer
// All possible icons for the cards
const allIcons = [
'fa-heart', 'fa-star', 'fa-smile', 'fa-sun', 'fa-moon', 'fa-tree',
'fa-bell', 'fa-gift', 'fa-leaf', 'fa-car', 'fa-home', 'fa-globe'
];
// Select the appropriate number of icons for the current level
icons = allIcons.slice(0, difficulties[level].pairs);
// Duplicate each icon to create pairs
icons = [...icons, ...icons];
// Shuffle the icons
shuffleArray(icons);
// Create a card for each icon and add it to the game board
icons.forEach(icon => {
const card = createCard(icon);
gameBoard.appendChild(card);
});
}
The Final Result:
if you want the full source code click on the download button below
disclaimer: you will get the source code, and to make it work in your machine is your responsibility and to debug any error/exception is your responsibility this project is for the students who want to see an example and read the code not to get and run.
Download Projects Source Code