Memory Card Game in JavaScript

Welcome to my blog , In this article you can build a Card Matching/Memory Card in HTML, CSS, JavaScript.

Current Video Link:

If you want to watch more videos subscribe my YouTube channel click here

we build Cool Card Matching/Memory Card Game in three steps:HTML,CSS and JavaScript Let’s Start

Memory Card HTML

First we will create a index.html and create timer div inside the header tag see below:

<header>
    <div class="timer">30</div>
</header>

After that create main game div inside show all flipper cards back and front portion div’s you can add more flip-container cards according your requirements.

<div class="game">
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
   <div class="flip-container">
      <div class="flipper">
         <div class="front"></div>
         <div class="back"></div>
      </div>
   </div>
</div>

Here HTML part is completed Now working on style.css below part have page design portion like body,header,game,card back and front part some header media queries.

Memory Card CSS

body {
  background: #FFEAC9;
  color: white;
  font-family: arial;
}
body header {
  height: 10vh;
  width: 100%;
  margin: 0 auto;
  position: relative;
}
@media screen and (min-width: 37.4375em) {
  body header {
    width: 600px;
  }
}
body header .timer {
  position: absolute;
  top: 14%;
  left: 3%;
  font-size: 23px;
  background: #FFAD29;
  width: 8vh;
  height: 8vh;
  line-height: 8vh;
  border-radius: 4vh;
  text-align: center;
}

.game {
  height: 90vh;
  width: 100%;
  position: relative;
  margin: 0 auto;
}
@media screen and (min-width: 37.4375em) {
  .game {
    width: 600px;
  }
}

.flip-container {
  -webkit-perspective: 1000;
  -moz-perspective: 1000;
  perspective: 1000;
  height: 22%;
  margin: 1%;
  cursor: pointer;
}

.flip-container.flip .flipper {
  -webkit-transform: rotateY(180deg);
  -moz-transform: rotateY(180deg);
  -ms-transform: rotateY(180deg);
  -o-transform: rotateY(180deg);
  transform: rotateY(180deg);
}

.flip-container, .front, .back {
  width: 23%;
  float: left;
  border-radius: 12px;
}

.flipper {
  -webkit-transition: 0.6s;
  -moz-transition: 0.6s;
  transition: 0.6s;
  -webkit-transform-style: preserve-3d;
  -moz-transform-style: preserve-3d;
  -ms-transform-style: preserve-3d;
  -o-transform-style: preserve-3d;
  transform-style: preserve-3d;
  height: 100%;
  position: relative;
}
.flipper .front, .flipper .back {
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  -ms-backface-visibility: visible;
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  box-shadow: #FFCCA9 0 8px 2px;
}
.flipper .front {
  -webkit-transform: rotateY(0deg);
  -moz-transform: rotateY(0deg);
  -ms-transform: rotateY(0deg);
  -o-transform: rotateY(0deg);
  transform: rotateY(0deg);
  background: #FF2151;
}
.flipper .back {
  -webkit-transform: rotateY(180deg);
  -moz-transform: rotateY(180deg);
  -ms-transform: rotateY(180deg);
  -o-transform: rotateY(180deg);
  transform: rotateY(180deg);
  border: 1px solid #E8E8E8;
}

Now below portion have each card images if you have need all same images that I used in Card Matching/Memory Card Game you can download click here

#piggy-bank {
  background: white url("piggy-bank.png") no-repeat center;
  background-size: contain;
}

#shoe {
  background: white url("shoe.png") no-repeat center;
  background-size: contain;
}

#plane {
  background: white url("plane.png") no-repeat center;
  background-size: contain;
}

#suitcase {
  background: white url("suitcase.png") no-repeat center;
  background-size: contain;
}

#robot {
  background: white url("robot.png") no-repeat center;
  background-size: contain;
}

#ring {
  background: white url("ring.png") no-repeat center;
  background-size: contain;
}

#palm-tree {
  background: white url("palm-tree.png") no-repeat center;
  background-size: contain;
}

#mp3 {
  background: white url("mp3.png") no-repeat center;
  background-size: contain;
}

Card Matching Game styling portion done after that working on script.js

Now First add some cdn’s in bottom of index.html this is mandatory.

<script src="https://static.codepen.io/assets/common/stopExecutionOnTimeout-157cd5b220a5c80d4ff8e0e70ac069bffd87a61252088146915e8726e5d9f147.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min.js'></script>
<script>
  window.console = window.console || function(t) {};
</script>

The Complete script.js portion you can directly copy and paste complete code in your script file.

You have 30 seconds to complete Game. if you not matching the same cards in 30 sec you loss the Game.

Memory Card ( JS/JavaScript )

$(document).ready(function() {
  //fallback for safari as it doesn't support vh
  if (navigator.userAgent.search("Safari") >= 0 && navigator.userAgent.search("Chrome") < 0) {
    $(".game").height( $(window).height() * 0.9 );
  }
    
    var cards = ['piggy-bank', 'shoe', 'plane', 'suitcase', 'robot', 'ring', 'palm-tree', 'mp3'];
    var pairs = cards.concat(cards);//create pairs of cards
    var chosenCards = [];
    var cardsToFlip = [];
    
    var gameStarted = false;
    var running = false;
    var outOfTime = false;
    var countdownStarted = false;
    var win = false;
    var pairCount = 0;
    var time = 30;
    
    shuffleArray(pairs);//shuffle cards
    
    $('.back').each(function(i, element) {
        $(this).attr('id', pairs[i]);//sets id in DOM for cards, access styles via css
    });
    
    $('.flip-container').click(function(){
        
        if (!outOfTime) {
        
            if (!gameStarted && !running){//before the game starts, show all cards to the user and flip back
                
                running = true;
                
                $('.flip-container').each(function() {
                    $(this).toggleClass('flip');
                });
                
                setTimeout(function() {
                    
                    $('.flip-container').each(function() {
                        $(this).toggleClass('flip');
                    });
                    
                    gameStarted = true;
                    running = false;
                    
                }, 2000);
            }
    
            else if ($(this).find('.back').attr('id') == chosenCards[0] && chosenCards[1] == null && $(this).hasClass('flip') && !running) {
                
                running = true;
                
                chosenCards[0] = null;//if one card has been chosen and then clicked again, flip back over
                $(this).toggleClass('flip');
                
                running = false;
                
            }
            
            else if ($(this).hasClass('flip')) {
                        
                return;//if the card clicked is already flipped, return
                
            }
        
            else if (chosenCards[0] == null && chosenCards[1] == null && !$(this).hasClass('flip') && !running) {
                
                if (!countdownStarted) {
                    countdown();
                }
                
                running = true;
                
                chosenCards[0] = $(this).find('.back').attr('id');//if no cards have been chosen, store the chosen card's in chosenCards[0]
                $(this).toggleClass('flip');
                
                running = false;
                
            }
        
            
            else if (chosenCards[0] != null && chosenCards[1] == null && !$(this).hasClass('flip') && !running) {
                
                running = true;
                
                chosenCards[1] = $(this).find('.back').attr('id');//if no second card has been flipped, store the chosen card's brand in chosenCards[1] and flip it
                $(this).toggleClass('flip');
        
                if (chosenCards[0] == chosenCards[1]) {
                    
                    chosenCards[0] = null;
                    chosenCards[1] = null;
                    
                    pairCount++;
                    
                    if (pairCount == cards.length) {
                        win = true;
                        alert("you win :D");
                    }
                    
                    running = false;
                    
                }
        
                else {//if the brands did not match - empty the chosenCards & flip the cards back over 
                    
                    cardsToFlip[0] = chosenCards[0];
                    cardsToFlip[1] = chosenCards[1];
                    
                    chosenCards[0] = null;
                    chosenCards[1] = null;
                    
                    setTimeout(function(){//flip back the chosen cards that did not match
        
                        $('*[id*=' + cardsToFlip[0] + ']').each(function() {
                            $(this).closest('.flip').toggleClass('flip');
                        });
                        $('*[id*=' + cardsToFlip[1] + ']').each(function() {
                            $(this).closest('.flip').toggleClass('flip');
                        });
                        
                        running = false;
                        
                    }, 800);
                }
                
            }
                
        } else {
            alert("you have run out of time :(");
        };
        
    });//Flip Container Click End
    
    function shuffleArray(array) {
        for (var i = array.length - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    }
    
    function countdown () {
        
        countdownStarted = true;
    
        var timeStart = +new Date;
        var timer = setInterval( function() {
            
            var timeNow = +new Date;
            var difference = ( timeNow - timeStart ) / 1000; //calculates time difference if game isn't in focus
            
            if (time > 0 && !win) {// if there is still time left and game isn't won, deduct time
                
                time = 30;
                time = Math.floor( time - difference );
                $('.timer').text( time );
                
            } else if (win) {//stop timer when game is won
                
                clearInterval(timer);
                
            } else {//stop timer when time is run out
                
                outOfTime = true;
                alert("you have run out of time :(");
                
                clearInterval(timer);
                
            } 
            
        }, 250 );
        
    };

});//Document Ready End

The HTML ,CSS AND JAVASCRIPT portion is completed if you like the article share with your friends.if you have any question or query related to article and have an any suggestions please leave in comment box.

Thanks for reading the Article

2 thoughts on “Memory Card Game in JavaScript

Leave a Reply

Your email address will not be published. Required fields are marked *