How to Create a Simple Card Matching Game in JavaScript Part 2

A Quick Review

In Part 1, we created our project, downloaded the assets, setup index.html, and styled our page. Now, we can actually start coding the game. If you stumbled across this page without reading Part 1, please read Part 1 before continuing. Let’s start coding!

 

Adding Variables

We can start of by adding a few variables.

// this will hold all the card values. I will explain why the array size is 5 and not 4 in a moment.
var cards = new Array(5); 

// numbers will hold track that each card can only appear 2 times.
var numbers = [0, 0, 0, 0, 0, 0, 0, 0]; 

// This will hold track of all the cards we matched up.
var got = [false, false, false, false, false, false, false, false]; 

// This will hold track of the previous card that we clicked.
var lastCard = null; 

// This will be the last index that was clicked(square, circle etc…) we will be using numbers from 1 to 8 instead of names, its easier this way.
var lastIndex = 0; 

// totalIncorrect will hold the number of tries the player took.
var totalIncorrect = 0;

// We'll prevent the user from clicking too much, spam clicking, and avoid any potential bugs that may be cause by this.
var isBuzy = false; 

 

Generating the Deck

With our variables set, let’s start writing functions that will generate the deck. Create the function addCards and place it after our variable declarations. The function addCards is our biggest function so we’ll break this up into chunks.

function addCards(documentId) {

To start our function off, we’ll create a variable called html that will hold the HTML output. We’ll be inserting the images into the html variable.

var html = "";

Next, we will create a 2D array that will hold all of our cards.

for(i = 0; i < 4; i ++){ // Loop trough the whole card array, and for each element create another array
 cards[i] = new Array(4); // in other words create a 4x4 grid of cards(2d array)
 for(k = 0; k < 4; k ++){ // then loop trough that array and set everything to 0
  cards[i][k] = 0;
 }
}

At the end of the array, we’ll insert the back image of the card and set it to 0.

cards[4] = new Array(1); // create a last element to hold the back image of the cards
cards[4][0] = 0; // also set it to 0 it will never change.

Here, we’ll add the images to our newly created array by appending the html variable with <img> tags.

for(y = 0; y &amp;lt; 4; y ++){ // now loop trough a 4x4 grid and add the images
 for(x = 0; x &amp;lt; 4; x ++){
  id = "\""+x + ":" + y +"\""; // creates an id for each image using the x and y position
  html += "&amp;lt;img id=" + id + " src=\""+getCardString(cards[x][y])+"\" style=\"animation:flipFront 5s\" onclick=\"flipCard("+x + ", " + y+")\"/&amp;gt;";
 } // creates a image with that id, also set the source to the back side of the card. We will be writing that // function next. Then set the on click method to run the flipCard function with parameters x + y.
 // also set it to animate the flipFront animation we created in the css file, it will run this for 5 seconds.
 html += "&amp;lt;/br&amp;gt;"; // add a new line after each row.
}

We’ll wrap up the function by calling generateCards and set that div element’s inner html to the code we just generated.

generateCards();//another method we will be creating that will randomize the cards.

document.getElementById(documentId).innerHTML = html; //now we set that div element’s inner html to the code we just generated.

} // don't forget the closing curly bracket!

And that’s it! All of your cards are now created in the center of the screen!

 

Getting The Cards

In the previous function we called getCardString() and now we are going to define it. getCardString() will use the index variable and then return a string that references to the image. It will either return the location of the back of the card or to one of the shape images.

function getCardString(index){
 if(index == 0)
  return "media/cards/" + "cardBack" + ".png";
 else
  return "media/cards/" + index + ".png";
}

 

Generate Cards

Our next function will generate the cards by assigning a random number to our 2D array of cards. We’ll loop through all of the card positions to make sure every slot is filled.

function generateCards(){
 for(x = 0; x &amp;lt; 4; x ++){ // Loop through the whole grid again(x)
  for(y = 0; y &amp;lt; 4; y ++){ // and this is the y tiles
   num = randomBetween(1, 8); // now we get a random number from 1 to 8, needs to be created.

   while(numbers[num-1] == 2){ // If the index has already been created twice we keep generating
    num = randomBetween(1, 8); // random numbers until we get one that has not yet been
   } // used

   cards[x][y] = num; // then we set our grid in that position to the random index
   numbers[num-1] ++; // and tell it that there is one more such index added.
  }
 }
}

Getting a Random Number

The randomBetween function takes in two parameters – a minimum number and a maximum number. Using Math.floor(), we’ll return a random number based on the minimum and maximum.

function randomBetween(min, max){
 return Math.floor(Math.random() * (max - min + 1) ) + min;
}

 

Flipping the Card

Now for the flipCard(x, y) function. This function will be called every time a card is clicked on. Lets see :

function flipCard(x, y){ // takes in the grid position of the card.
 if(got[cards[x][y]-1] || isBuzy) // check if an animation is busy or that the user
  return; // did not yet get that combination otherwise skip the rest.
  e = document.getElementById(""+x + ":"+ y+""); // now we set a variable reverencing the clicked card.
  e.style.animation = "flipBack 1s"; // set the animation to flipBack for 1 second
  isBuzy = true; // show that is buzy animating
 
  setTimeout(function(){ // now we wait until the animation is done(1 second) and then call displayPic(x, y, e)
  displayPic(x, y, e) // Lets go have a look at this function.
 }, 1000);
}

 

Displaying Picture

The displayPic() function takes in the grid x and y position as well as the card that has been clicked. When clicked, we’ll add the flipFront animation and then after a short delay, we’ll check the card.

function displayPic(x, y, e){
 e.src = getCardString(cards[x][y]); // here we set the picture to the correct image
 e.style.animation = "flipFront 1s"; // add the ending animation(grow)

 setTimeout(function(){ // wait for the animation to be done again.
 checkCards(x, y, e) // then we call this function.
 }, 1000);
}

 

Check Cards

The checkCards(x, y, e) function takes in the same parameters as the previous function and then matches the cards. Lets take a look on how it does that.

function checkCards(x, y, e){

 if(x == 4) // Checks if the cards did not match then skip the rest.
  return;
  isBuzy = false; // The animation is done now

  if(lastCard != null){ // Check if we clicked on a previous card.

   if(cards[x][y] == lastIndex){ // check if the current card index is the same as the previous index

    got[cards[x][y]-1] = true; // set that we got the combination.
    lastCard = null; // set last card to null so we can start over with the selection.
    checkWin(); // I will cover this next. This is the last function we will need.

    return; // then return to skip the rest.
  }

  e.style.animation = "flipBack 1s"; // if it was incorrect run the animation for the current card

  lastCard.style.animation = "flipBack 1s"; // run the animation for the previous card(shrink)

  n = lastCard; // set a variable for the previous card because we will be setting it to null
  lastCard = null; // set the previous card to null because we need to restart the selection
  totalIncorrect ++; // increase the amount of tries.

  setTimeout(function(){ // wait for the animation
   displayPic(4, 0, e); // set the cards images to the card back image and make them grow again
   displayPic(4, 0, n); // uses the temporary variable we created from the previous card
  }, 1000);

 } else {
  lastCard = e; // if this is the first click, then set the last card to this one
  lastIndex = cards[x][y]; // set the last index to this one.
 }
}

 

Check Win

Now for the last function then you will have a card match game, the checkWin function! This function will loop through all of our card sets and if all of them are matched, we’ll display a popup to the user and let them play again.

function checkWin(){ // takes no parameters
 for(i = 0; i < 8; i ++){ // Loops trough all the combinations we got.
  if(!got[i]){ // if it finds one that we don’t have yet skip the rest
   return;
  }
 }

 // asks the user if he/she would like to play again.
 if (window.confirm("Congratulations! You Won!! You had " + totalIncorrect + " incorrect moves!, go again?")) {
  location.reload(); // reload the page if ok was pressed.
 }
}

 

And there you have it, a javascript card matching game! If you have any questions about Part 1 or Part 2, please let me know in the comments below. I’ve also created a repo on GitHub at https://github.com/gamebuildingtools/Card-Matching-Game-with-JavaScript where you can see the full working code.

Final output of Card Matching Game
Daniel Williams

One thought on “How to Create a Simple Card Matching Game in JavaScript Part 2

  1. Pingback: How to Create a Simple Card Matching Game in JavaScript Part 1 - Game Building Tools

Leave a Reply

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