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");
    images.push(img);
    images.push(img);
  }
}
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);
  visibleImages.fill(false);
  shuffle(images, true);
}
function draw() {
  background(255);
  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…

ezgif.com-gif-maker (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.

Cheers
— mnse

3 Likes

Yeah!

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.

remark

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

2 Likes

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

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

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");
      }else 
      {
       // 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

That’s okay, just say 0

We define them in mousePressed()

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
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

2 Likes

Do you have a You Won message?

1 Like

Yes! I add a counter to counter the no. of pairs that match. If it is >=8 it will win and show the You Won message!

1 Like

Well done! Congratulations!

1 Like

That’s true!

Please (after shuffling) use the 2nd for loop (from the preload function) again to load the images again. Then the two arrays will match again.

2 Likes

Between these two lines.

From an architectural perspective you could consider writing an function initialize() that you call from preload AND from your reset section.

Because the two parts (in preload and reset) are almost the same.

Unless you load another set of images upon reset.

1 Like

I am not sure about that.

please try this instead:

function keyPressed() {
  if (key == 'r'||key == 'R') {
    restart = true;
    print("here");
  }
}

Do you receive the word “here” in the console?

1 Like

yes!
I can receive the word “here”