How do I Select and DESELECT cards in a Match-4 card game ?

Just started using Construct 2? Post your questions here

Post » Fri Aug 07, 2015 9:29 pm


I'm trying to make an educational game. It is for teaching chemistry, but you definitely don't need to know chemistry to know how the game works, or to help answer this question. Instead of explaining how the game works using chemistry, I've used an analogy that describes the game without any real change in the mechanics - that is, an analogy using a normal deck of cards. (If you do want to know about the chemistry, I've explained the game that way at the end of this post, it is first-year organic chemistry/intro organic chemistry, the idea being to familiarise students with different representations of chemical compounds).

(I've highlighted 'the problem' in black so if you want to only read that, jump down to it). If anyone needs any further explanation about anything, let me know and I'll be happy to do that.

The game
Imagine there are 16 cards are depicted, face up. All cards are the same size. (In my game I call the cards 'Squares'). They are randomly selected so that we have 4 cards from each suit (so four cards, any four, of the 'Hearts' suit, four of the 'Diamonds' suit, four from the 'Clubs' suit and four from the 'Jacks' suit). Every card is unique (we don't have two Ace of Diamonds, but we might have an Ace of Diamonds and an Ace of Clubs). We don't see every card from every suit.

I've only used 1 Sprite object (called 'Square') to depict the different cards - each animation cell has a different card 'frame': the first 4 animation cells (animation frame=0 through animation frame=3) are of the same 'category'/suit. The next four animation frames are of the same category/suit, and so on.

The players job would be to click/touch the cards that belong to each suit - for instance, a player might select the 4 of Clubs, the Ace of Clubs, the 9 of Clubs and the Queen of Clubs. When this happens, they get a 'match'. The four cards they selected disappear, and now there are only 12 cards left, each belonging to one of 3 suits (Diamonds, Hearts or Jacks).

I spent hours and hours trying to figure out how to have a 'select'/'deselect' graphic. Finally, I figured it out, and it was far more simple than I'd thought (I've described how I did it at the end of this post since I don't want to clutter it up, I am long winded and I don't want to drone on too much). Basically, when the student taps or clicks a Square, it highlights blue. This means it has been Selected. When they tap the selected Square again, it returns to the normal colour, meaning it has been de-selected.

Now, when a student has selected four Squares, the game checks if all four Squares belong to the same 'category'/'suit'. If YES, then the Squares are destroyed, as I mentioned before. If NO, the Squares are all unselected, and the player must try again, and this goes on until all the Squares are gone.

The problem:

I cannot figure out how I should 'store' the Squares information, so that when 4 cards are selected, the computer calculates/compares them, to check if they belong to the same category.
Previously, I had abandoned the idea of 'deselection' so a student could only SELECT cards, and could not change their mind until four cards had been selected.

But now, when a student selects a card, I want them to be able to change their mind and deselect the card, then select a new card. Previously, with no 'deselect' capability, I was just using a set of four global variables, e.g. 'FirstSelection', '2ndSelection', '3rdSelection' and '4thSelection'. Each time a player selected a card, the animation frame would be stored in the corresponding global variable (so if they were choosing their first card, the animation frame number would be stored in 'FirstSelection', and so on, until 4 cards were chosen, at which time the four variables would be added up, or shunted into an expression, and if the expression equalled a certain number, the student would get a match, and the Squares would disappear).

But now, if the student selects a Square, e.g. they choose a 9 of Diamonds for their first selection, but then they want to change it to a 9 of Clubs (and lets say the 9 of Diamonds is drawn in animation frame 0, for the sprite 'Square', and the 9 of Clubs is drawn in animation frame 4 of the same sprite).

Using the code I've got now, the game would set the 'FirstSelection' variable to 0 (corresponding to the student's first choice).

But since they have changed their mind and deselected the 9 of Diamonds, and now selected the 9 of Clubs, the variable 'FirstSelection' has to change as well.

But I don't know how to code this. I'm completely baffled by this actually. I am only thinking vaguely, like, a condition 'when 1 card is selected, add the number of the AnimationFrame of the Square that is selected, to the global variable 'FirstSelection' - but if this card is DESELECTED, then the variable should be reset (to -1, say), and then if another card is chosen in its place, the Animation Frame value of that card should be added to the 'FirstSelection' variable.

And the thing is, maybe the student selects 3 Squares/cards, and then looks at the 3 Squares, and sees that the SECOND and THIRD selections are okay, but the FIRST selection is wrong. So the student deselects the Square, and selects another one. So, at any time, the student should be able to replace any selection (until 4 cards are selected, at which point the game will evaluate to see if they are all of the same category).

I hope this is not too confusing. I will upload the CapX file for the game if anyone wants it, but I have to warn you that it is a bit messy and hard to navigate. I based the game structure on a Card Matching game I found somewhere here (it is in a tutorial actually) where a Deck of cards is shuffled and random cards are laid out on a screen face down, and the player selects 2 of these cards, which must be the same value cards but from different suits (e.g. the 9 of Diamonds, the 9 of Clubs). I think that is how it worked. I laid my game over that framework, removing the concept of 'facedown', since I want the students to see all the Squares/cards at all times. From there, I just customised the game so it works for 4 cards, and have added in chemical structures/formulae as the animations.

Any help at all, I would greatly appreciate. I am getting desperate actually ! It is a weird mode of thought, making this game, and it is unfamiliar to me. I spend hours trying to determine the best way and I often think of very complicated ways, but it nearly always turns out that simplest is best. However, I don't have a very fluid mind, I think my brain is good at retaining facts, but less so at logical explanations (or concise ones).

Thanks in advance,
All the best,

The organic chemistry/the actual game

The cards analogy is quite fitting for the game. Instead of Clubs/Hearts/Diamonds/Jacks, I am using different categories, based on functional groups. The first level, the easiest, has alkanes, alkenes, alkynes and cycloalkyl compounds. For the alkanes functional group, they will see a square with the name of an alkane (e.g. ethane), a square with ethane's chemical structure (the skeletal structure for ethane), a square with ethane's molecular formula (the lowest whole number ratio of carbon and hydrogen atoms in the compound, so for ethane that would be C2H6, and finally, a square with 'alkanes' written on it (i.e. the functional group type/classification).

Again if you need or want or would like any more info, or anything else, please let me know, I'll only be too happy to provide it. Thanks again.
Posts: 7
Reputation: 264

Post » Fri Aug 07, 2015 10:27 pm

So I have advanced this a bit, I'm quite happy:

I used the following:

On the condition that 'Number of Squares Selected' = 4 (i.e. when four squares are selected by the player), no action but a subevent, and a local variable 'IncreasingVarForArrayIndex' with initial value = -1

The conditions of the subevent:
For each 'Square'
Square instance variable 'isSelected' = 1

The actions of the subevent:
Add 1 to local variable 'IncreasingVarForArrayIndex'

(and for a new 1D array of slots (4,0) called 'aSelectedFrames': Set value at 'IncreasingVarForArrayIndex' to Square.FG)

When the Square is selected by the user, the instance variable 'isSelected' changes from 0 to 1. So, the user selects 4 cards, and then the array receives the number for each 'category' (in a deck of cards, the categories would be the suits: each card would have an instance variable 'Suit', which for Clubs cards would = 1, for Diamonds = 2, for Jacks = 3, and for Hearts = 4).

(In reality, I'm using chemistry categories, and the four categories are just 4 different functional groups - they can be any functional groups, the first level uses alkanes (instance variable 'FG' = 1), alkenes (FG=2) alkynes (FG=3) and cycloalkyls (FG=4).

So now I've got the FG instance variable of all four selected cards, into the array. From here, I can easily (I think), have the system evaluate whether each of the four FG values in the array are the same. So if the Squares selected are all from the same category, then FG of each card = x (where x = 1, 2, 3 or 4), then this means the Squares are matches.

To avoid the select/deselect problem, I only want to evaluate the FG instance variable of each card/Square, once the student has selected FOUR cards. (So, when they select the first or the second or the third card, I don't want anything to happen, because I think it is simpler just to evaluate the cards once four are picked, this way there is no 'first' or 'second' or 'third' card, there are just four cards and each can be checked at the one time).

When I run the game, I select four cards, the four cards' FG values are placed in the array, no worries there.

So the next task, is to have the computer evaluate the FG value in each array slot to see if they are all the same ! If this works, then I will have the computer destroy those cards and so there'll be only 12 cards left, then 8, then 4 ! So this is really good. Writing it out really helps me think actually.

Hopefully I'll solve this - I think I'm nearly there.
Posts: 7
Reputation: 264

Post » Sat Aug 08, 2015 9:29 am

Although you seem to be going the right way, this capx might come in handy

Select only 3

When the player selects more than 3 the first one he selected gets automatically deselected.
I told my dentist I had trouble with my teeth and asked her to fix it without looking in my mouth..
Posts: 6,160
Reputation: 19,775

Post » Wed Aug 12, 2015 6:48 am

Hi LittleStain, thanks for the response and the CapX. Basically I've completed the visual select/deselect stuff.

The problem I'm having now, is how to actually remove/destroy all the selected cards when they match (i.e. when the instance variable FG = x for the first, second, third and fourth cards, where x = either 1, 2, 3 or 4...if one or more cards has a different FG value to the others, then there's no match).

So like I was saying in the last post, I started with:

(Note: FG is the instance variable on every card/Square that defines the category, it can be either 1, 2, 3 or 4, and 'isSelected' is the instance variable on every card/Square that describes if the card is selected or not. If the card is selected, then isSelected = 1, else 0).

localvar = IncreasingVarForArrayIndex = -1
The sprite for the squares/cards is called 'Square1'

The first group is 'On 4 cards selected'

gCardsPicked => 4
..For Each sprite Square1
..Square1 'isSelected'=1
---> Add 1 to IncreasingVarForArrayIndex
---> Set at X for the array 'aSelectedSquares' (set value at 'IncreasingVarForArrayIndex' to Square1.FG)

..Trigger once
---> Add 1 to 'Turns'
---> Stop loop

Next group: 'Remove Matches'

On array 'aSelectedSquares', for Each X Element
..Current value in array 'aSelectedSquares' = aSelectedSquares.At((aSelectedSquares.CurX)+1)

After all the FG values are set into the 'SelectedSquares' array (4 values total), then each value in the array should check against the value 1 higher than itself.

eg. lets say I select cards with FG = 1, for each card. The X value at the array index 0, will = 1. The X value at the array index 1 will equal 1, the X value at the array index 2 will equal 1, and the X value at the array index 3 will equal 1.

So during the For Each X Element, the loop will compare the Current Value, to the value stored in the next array element. If all four values in the array are equal, then the cards should be destroyed.

The problem is, the last array value. So when the X element in the For Each X Element in the array = 3, then the value in the array will be either 1, 2, 3, or 4...but, if I use the compare Current Value = array.At(array.CurX)+1), then I think this will check for the value in a non-existent 4th array element, since (array.CurX=3) so array.At((3)+1)) = array.At(4)

Should I use two different conditions here ? How can I make the game/system check if all the values in an array are equal ?

Thanks for any help. I apologise again for my long and overly complicated way of doing things, I am trying to be more logical and concise but it is difficult. Thanks again.
Posts: 7
Reputation: 264

Return to Beginner's Questions

Who is online

Users browsing this forum: No registered users and 1 guest