Memo is an exaple of memorisation and matching games. There can be many variations but one of the most popular is based of finding a pair of cards.
Game starts with a grid of shuffled card pairs. A player sees the grid opened (i.e. all cards visible) for a short period of time and player's goal is to memorise as much as possible.
After it the game starts - all cards become hidden as well.
On each move player opens a pair of cards. If they are the same - the cards are left open. Otherwise - the cards get closed.
Game ends when all cards are open.
This project will implement exactly this version of the game. For it we will use vanilla JavaScript without any libraries.
Link to Wikipedia: https://en.wikipedia.org/wiki/Matching_game
Here is a live coding session that shows how it can be done.
Duration: 4:23 (coding - 4:14)
Disclaimer: never use this code in production. It was created for fun.
Let's break down the solution and comment on some complex or interesting things.
0:04 - starting with HTML template. Game field will be represented with table
and each card will be a td
element.
As in other similar projects the game field is generated dynamically - iterating height
times by width
times.
Few variables are defined - width
and height
represent dimensions of game field, pairs
is a number of pairs that should be opened. Important fact - at least one of width
or height
should be even.
cells
2-dimensional array will store the following infrmation for each cell (or card):
element
- link to corresponding HTML element, in this case it is td
value
- value of the cardopen
- flag is the card is opened or
0:55 - define styles. Not inventing anything complex - assume that every card will be a 75x100px block.
At this point you can see first results in the browser.
1:15 - implement function to open a card - openCard
.
Goal of this function is replace grey background with something colorful and display a number in the card.
Interesting part is how to calculate background colors. As in other projects we are using hsl
color model here using the following expression:
e.setAttribute('style', 'background-color: hsl(' + (320 * c.value / pairs) + ', 100%, 50%)');
Where c.value
is number shown on the card (e.g. 1, 2 or 3) and pairs
is number of pairs in the game.
In general, gradient looks like this:
1:38 - closeCard
function does the opposite - it removes text from the card and changes background to grey (by removing style
attribute from HTML element).
1:49 - each game starts with shuffling of the cards.
shuffle
function starts with generating an array called cards
containing pairs * 2
cards.
Then for each cell of the game field we pick a random element of cards
array and store it as value
of cells
array.
Also we should not forget that the game starts with opening all cards - we need to call openCard
for each cell.
After this step our game field will be shuffled.
2:30 - however after game is started we need to wait for a couple of seconds and close all cards.
For that we need closeAllCards
function that will just close all cards one by one.
And we schedule execution of this function after 2 seconds using setTimeout
function.
2:52 - next step is to handle clicks on the cards.
We need to add a click event handler to each table's cell.
select
function contains the logics and handles the following scenarios:
3:45 - last part is to check if the game is over or not.
The criteria is very simple - game is not over if there is at least one open card.
If there are no closed cards left - we consider it as won game. We show a Game over
message and restart the game.
This concludes the implementation and we can check results in the browser.
As you see the game is very simple and there are few things that you can improve:
Sources: https://github.com/5minute/examples/tree/main/memo
See live results:https://jsfiddle.net/0vayk7p4/