How to make a card matching game in p5.js (memory)

I am trying to make a card matching game. But I don’t know how I can matching than when they are correct. Maybe I can let the first card and second card . But I don’t really know how to do it.
Link: p5.js Web Editor

 let images = [];
let visibleImages = new Array(16);
let x = 0;
function preload() {
  for (let j = 0; j < 8; j++) {
    let img = loadImage(j + 1 + ".jpg");
function mouseClicked() {
  let cx = floor(mouseX / (width / 4));
  let cy = floor(mouseY / (height / 4));
  let imgIndex = cy * 4 + cx;
  visibleImages[imgIndex] = true;
function setup() {
  createCanvas(400, 400);
  shuffle(images, true);
function draw() {
  for (let j = 0; j < 4; j++) {
    for (let i = 0; i < 4; i++) {
      square((i * 400) / 4, (j * 400) / 4, 400 / 4);
      let imgIndex = j * 4 + i;
      if (visibleImages[imgIndex] == true) {
        image(images[imgIndex], (i * 400) / 4, (j * 400) / 4, 400 / 4, 400 / 4);
1 Like

Hi @yoyo,

Would you please follow the instructions and format your code… (1)

For a starting point you can put your images to an object with an id. Afterwards you can compare if the id is the same.

— mnse



Instead of using a class:
You also could load the image names into a String grid first.

Shuffle the string grid.

Load then the images into a second image grid (the one you already have)

Now you have the string names and can compare the names easily (numbers at start of String) to find out whether the 2 images match

next step

Have a counter for the mouse clicks. When it’s ==2 then compare the 2 open images, then reset. Thus you can distinguish between first and second mouse click.


Also draw an image for images that are not open (the backside of each card), the same image for every card.


how can I load the image names into a String grid?

Replace this by

imageNames.push (j + 1 + ".jpg");
imageNames.push (j + 1 + ".jpg");

imageNames : declare this as a new array

1 Like

(post deleted by author)

This part doesn’t belong there

After loading the names (after the for loop), first shuffle them.

Then load the images using the names (in a new for loop in setup()). Since the names are with duplicates you don’t load each image twice but just once

Thus we make sure that the two grids are parallel in the sense that the image name and its image are in the same cell of the grid. Only then can we do a comparison using the String name

  • Remember when comparing Strings later you can’t use == ; use s1.equals(s2) instead

(post deleted by author)

Where you have this in mouseClicked (better use mousePressed()) introduce a counter as explained above.

counter ++;

if(counter==1) {
  let imgIndex1 = imgIndex;
else if(counter==2) {
  counter=0; // reset
  let imgIndex2 = imgIndex;
  If(imagesName[imgIndex1].equals (imagesName[imgIndex2] )) {
      // ok
      println ("good");
       // wrong 
       // close both cards again !!!
       visibleImages[imgIndex1] =false;
       visibleImages[imgIndex2] =false;
       println ("No.");

  • counter :: make it a global variable, imgIndex1 and
    imgIndex2 as well

Good progress here!

This should be after the for loop, not inside of it

So it’s between the two for loops

(post deleted by author)

1 Like

That’s okay, just say 0

We define them in mousePressed()

(post deleted by author)

I don’t know.

Maybe I was wrong about .equals()... (probably true in processing but not in p5.js)

Just try

if (imagesName[imgIndex1] == imagesName[imgIndex2]) {
      // ok

You also need to count
correct pairs.

When == 8 you won

1 Like

(post deleted by author)

(post deleted by author)

1 Like
let imgIndex1;
let imgIndex2;

define both before setup ()

Remove the let in the old position in the code

1 Like

OMG, I did it!!! Thank you guys


Do you have a You Won message?

1 Like