Welcome to a beginner’s tutorial on how to create a simple memory game in Javascript. Interested to learn how to create browser games in Javascript? Or looking for a simple project to do? Then the class memory game is a good place to get started since it is not too complicated – Read on to find out!
TABLE OF CONTENTS
JAVASCRIPT MEMORY GAME
All right, let us now get into a demo of the memory game, and some details of the mechanics.
MEMORY GAME DEMO
PART 1) THE HTML
<div id="mem-game"></div>
HTML is the easiest component, we will use Javascript to generate the <img>
cards into <div id="mem-game">
. That’s all.
PART 2) THE CSS
/* (A) CONTAINER */
#mem-game {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 10px;
max-width: 420px;
margin: 0 auto;
}
/* (B) CARDS */
.mem-card {
padding: 10px;
cursor: pointer;
background: #e5e5e5;
}
.mem-card.open { background: #fea; }
.mem-card.right { background: #b3ffc0; }
.mem-card.wrong { background: #ffb6b6; }
- The important part here is essentially
display: grid
andgrid-template-columns: auto auto auto auto
. CSS literally does the rest of the layout magic. - The rest are kind of self-explanatory too.
.mem-card.open
is the style for opened cards..mem-card.right
for cards that are correctly matched..mem-card.wrong
for cards that are wrongly matched.
PART 3) BASIC JAVASCRIPT MECHANICS
var mem = {
// (A) PROPERTIES
// (A1) HTML ELEMENT
hWrap : null, // html game wrapper
// (A2) GAME SETTINGS & FLAGS
url : "https://code-boxx.com/wp-content/uploads/2019/08/", // optional,
moves : 0, // total number of moves url to images
sets : 6, // number of sets to match
grid : [], // current game grid
matched : 0, // number of sets that have been matched
last : null, // last opened card
lock : null, // timer, lock game controls when showing mismatched cards
hint : 1000, // how long to show mismatched cards
// ...
}
- Captain Obvious,
var mem
holds all the game mechanics. - There are quite a number of flags, but the essentials are:
mem.sets
We define the total number of sets to pair.- Since there are 6 images in this example,
mem.grid
will be an array of 12 (randomly shuffled) HTML images to pair. - As the player matches a pair correctly, we track it with
mem.matched
; Whenmem.matched == mem.sets
, the game ends.
PART 4) PRELOAD IMAGES
// (B) PRELOAD
preload : () => {
// (B1) GET HTML GAME WRAPPER
mem.hWrap = document.getElementById("mem-game");
// (B2) PRELOAD IMAGES
let img, loaded = -1;
for (let i=0; i<=mem.sets; i++) {
img = document.createElement("img");
img.onload = () => {
loaded++;
if (loaded == mem.sets) { mem.reset(); }
};
img.src = `${mem.url}smiley-${i}.png`;
}
},
window.addEventListener("DOMContentLoaded", mem.preload);
mem.preload()
is the first thing that runs on window load. Shouldn’t be too difficult to understand – We preload all the images before proceeding to start the game.
PART 5) START/RESTART GAME
// (C) RESET GAME
reset : () => {
// (C1) RESET ALL FLAGS
clearTimeout(mem.lock); mem.lock = null;
mem.moves = 0; mem.matched = 0;
mem.last = null; mem.grid = [];
for (let s=1; s<=mem.sets; s++) {
mem.grid.push(s); mem.grid.push(s);
}
// (C2) RANDOM RESHUFFLE CARDS
// credits : https://gomakethings.com/how-to-shuffle-an-array-with-vanilla-js/
let current = mem.sets * 2, temp, random;
while (0 !== current) {
random = Math.floor(Math.random() * current);
current -= 1;
temp = mem.grid[current];
mem.grid[current] = mem.grid[random];
mem.grid[random] = temp;
}
// (C3) CREATE HTML CARDS
mem.hWrap.innerHTML = "";
for (let id in mem.grid) {
let card = document.createElement("img");
card.className = "mem-card";
card.src = `${mem.url}smiley-0.png`;
card.onclick = () => mem.open(card);
card.set = mem.grid[id];
card.open = false;
mem.hWrap.appendChild(card);
mem.grid[id] = card;
}
},
Now, this looks confusing, but keep calm and look carefully.
- (C1) We reset all the game flags. In particular, regenerate
mem.grid
in running order –[1, 1, 2, 2, 3, 3, ... 6, 6]
- (C2) Reshuffle
mem.grid
randomly. - (C3) Loop through
mem.grid
and generate the HTML images.
PART 6) SELECT A CARD
// (D) OPEN A CARD
open : card => { if (mem.lock == null) { if (!card.open) {
// (D1) UPDATE FLAGS & HTML
card.open = true;
mem.moves++;
card.src = `${mem.url}smiley-${card.set}.png`;
card.classList.add("open");
// (D2) FIRST CARD - SET IN LAST
if (mem.last == null) { mem.last = card; }
// (D3) SECOND CARD - CHECK MATCH
else {
// (D3-1) REMOVE CSS CLASS
card.classList.remove("open");
mem.last.classList.remove("open");
// (D3-2) MATCHED
if (card.set == mem.last.set) {
// UPDATE FLAGS + CSS
mem.matched++;
card.classList.add("right");
mem.last.classList.add("right");
mem.last = null;
// END GAME?
if (mem.matched == mem.sets) {
alert("YOU WIN! TOTAL MOVES " + mem.moves);
mem.reset();
}
}
// (D3-3) NOT MATCHED - CLOSE BOTH CARDS ONLY AFTER A WHILE
else {
card.classList.add("wrong");
mem.last.classList.add("wrong");
mem.lock = setTimeout(() => {
card.classList.remove("wrong");
mem.last.classList.remove("wrong");
card.open = false;
mem.last.open = false;
card.src = `${mem.url}smiley-0.png`;
mem.last.src = `${mem.url}smiley-0.png`;
mem.last = null;
mem.lock = null;
}, mem.hint);
}
}
}}}
When the player picks a card, a number of things happen.
- (D1) We set
card.open = true
to mark the card as “currently open”; Clicking on this card while it is already open does nothing. - (D2) Remember this game is about matching pairs? If it is the first opened card, we simply set it into
mem.last
. - (D3) On opening the second card, we check if it matches with
mem.last
.- (D3-2) Increment
mem.matched
if it is a match, check if the game has ended. - (D3-3) If not, we let the cards remain open for a second before closing both of them.
- (D3-2) Increment
DOWNLOAD & NOTES
Here is the download link to the example code, so you don’t have to copy-paste everything.
SORRY FOR THE ADS...
But someone has to pay the bills, and sponsors are paying for it. I insist on not turning Code Boxx into a "paid scripts" business, and I don't "block people with Adblock". Every little bit of support helps.
Buy Me A Coffee Code Boxx eBooks
EXAMPLE CODE DOWNLOAD
Click here for the source code on GitHub gist, just click on “download zip” or do a git clone. I have released it under the MIT license, so feel free to build on top of it or use it in your own project.
EXTRA BITS & LINKS
That’s all for this project, and here is a small section on some extras and links that may be useful to you.
GAME RULES
For the people who somehow cannot figure the game out…
- There are a number of “cards” that are scattered randomly across a grid in pairs.
- The player opens a pair of cards in the grid – If the cards match, that is “one point” and the player will continue to find the next pair.
- But if the cards don’t match, they will “fold back” to become hidden.
- The player will have to try to remember all the positions of the cards and match all of them to win.
COMPATIBILITY CHECKS
- Arrow Functions – CanIUse
- Template Literals – CanIUse
This example will work on all modern “Grade A” browsers.
LINKS & REFERENCES
- Javascript BlackJack – Code Boxx
- Javascript MineSweeper – Code Boxx
- Javascript Hangman – Code Boxx
- Javascript Quiz – Code Boxx
- Javascript Memory Game – Code Boxx
- Javascript Number Guessing Game – Code Boxx
- Javascript Tic-Tac-Toe – Code Boxx
- Javascript Rock Paper Scissors Game – Code Boxx
- Matching Game – Wikipedia
- Emoji Icon set on Pixabay (free to use)
THE END
Thank you for reading, and we have come to the end of this guide. I hope that it has helped you with your project, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!
Many thanks, great help.
I learn always best from great examples.
Al