Flipping Tiles (Memory game) using Python

Anyone can test their memory by playing the flipping-tiles game. Each number or figure has a pair of tiles in this set, which is an even number. We must flip the tiles so that we can see them because they are facing down. One flips two tiles in a turn, and if they match, they are taken out. If not, they are turned around and put back into position. Until all of the tiles have been matched and eliminated, we continue in this manner.

Introducing the game :

The tiles in our grid can now be displayed either face up or face down. But there is no way for us to engage in the game itself. Here's a reminder of how the game operates :

  • All of the tiles are face down as the game begins.
  • The player then turns over two cards and clicks on them to choose
  • The tiles stay face up if they have the same image. If not, they must be turned face down once more after a little interval.

Flipping clickable tiles :

We currently have a programme that merely draws a tile grid before stopping. As time goes on, we want our programme to generate a variety of images. It will initially draw face-down tiles, followed by clicked tiles and a win screen if everything goes according to plan for the player.

Moving all of our drawing code to this language draw() function is the next logical step. While the application is running, the computer will continue to execute draw(), causing the tiles to continue to be drawn based on whether they are facing up or down.

Now let's turn a few of those tiles face up! The player must click on a tile in order to flip it. In This language projects, we can write a mouseClicked() function to respond to mouse clicks, and the computer will run that code each time the mouse is clicked.

When our application notices that the player has clicked someplace, we want to use mouseX and mouseY to detect if they have clicked on a tile. Let's begin by giving Tile an isUnderMouse() method that returns true if a given x and y are inside the area of a tile.

The x and y of the tile correspond to the upper left corner of the tile because the way we've created the tiles, thus we should only return true if the provided x is between this.x and this.x + this.size and if the provided y falls between this.y and this.y + this.size.

Since we have that method now, we can check in mouseClicked() to see if each tile is within the mouseX and mouseY using a for loop. If so, then we set the isFaceUp() property of the tile to true.

Restricting the flipping of cards :

The player's ability to flip the tiles over is a feature we should've developed, however we've left out a crucial limitation : - users shouldn't be capable of flipping more than two tiles at once.

The number of flipped tiles will need to be recorded in some way. One straightforward approach would be to use a global variable called numFlipped that we increment each time a player turns a card face up. If numFlipped would be less than 2 and the tile isn't already face up, we only flip it over :

Delaying of the tile's flipping :

So, the logic behind flipping two tiles is finished. Next, what? Let's go over the guidelines once more :

The tiles stay face up if they have the same image. Otherwise, after a while, the tiles turn back around.

It will be difficult to test the first portion if we can't simply seek for fresh matches, so we will first develop the second component, which automatically flips the tiles back over.

By setting isFaceUp to false, we know how to reverse the direction of the tiles, but what about after some time has passed? Delaying code execution takes many forms in different languages and environments, and we need to figure out how to achieve it in This language. In order to determine if the delay period has passed, we need a mechanism to keep track of time. We also need a way to call code once the delay period has ended. What we would advise is this :

  • We created the delayStartFC global variable, which was initially empty.
  • After flipping over a second tile in the mouseClicked() method, we kept the present value of frameCount in delayStartFC. One way we may tell the time in our programmes is by using the variable that indicates how many frames have passed since the programme began to execute.
  • In the draw() function, we determine whether the new frameCount value is much higher than the previous one. If so, all of the tiles are turned over, and numFlipped is set to 0. Additionally, we nullized delayStartFC.

In fact, it's a wonderful solution that doesn't involve writing a lot of code. We may use the loop and noLoop methods to ensure that the draw code is only called when a delay is present in order to improve performance. Here's everything we explained :

Checking the matches :

If we were able to match any of the tiles above, we were likely disappointed when they were turned back over because, hey, we were successful! So it's time to put this game rule into action :

When two tiles line up perfectly, they should remain face up.

This indicates that whenever there are two flipped over tiles, as well as before the user set up the delay, we should look for matching tiles. Pseudo-code for that would be :

How do we determine if two tiles are facing the same direction? We already have a checked for this (numFlipped === 2). First, we need a way to get at the two tiles that are faced up. How can we locate them?

Each time, we could traverse over our array to identify all of the tiles whose isFaceUp property was set to true before storing those into another array.

Let's take a short cut and always keep our flipped tiles inside an array for convenience. By doing this, each time the player flips a tile, we avoid having to loop through the entire array of tiles.

We may first swap out numFlipped for an array, then use flippedTiles.length wherever numFlipped was previously used. This is how our mouseClicked() function looks :

Now, identifying whether the two tiles in the flippedTiles array indeed have the same face requires further investigation. What is the face property, then? It's an object, and since the variable is directing at the same location in computer memory for each, the face of matching tiles should actually be pointing at the exact same item. This is due to the fact that each image object was only ever created once (for example, getImage("avatars/old-spice-man")), and that object was then twice pushed onto the faces array :

If two variables that refer to objects are used, and if both of those variables correspond to the same object in memory, then the equality operator, at least in JavaScript, will return true. As a result, we can do a quick check by using the equality operator on the face property of each tile.

We must keep the tiles up now that we are certain they match. They would all currently be turned over after some delay. We could simply choose not to set up the animation in this scenario, but we can't rely on that as there will be an animation in subsequent turns.

We need a method to be able to say, "Hey, when we turn them all back, we should not turn these specific ones over." That is a good application for a boolean property! Let's add the isMatch property to the Tile constructor and then just inside that if block, set the isMatch property to true. It is shown below too :

We can now decide regarding whether to flip the tiles over with or without the delay using that property.

Complete Code :

Output:

Flipping Tiles (Memory game) using Python
Next TopicPython Curl