Lingo Game: Memory

File "memory_game.dir"

In this classical game, an even number of cards are arranged face-down on a table in a rectangular fashion. One or more player(s) take turns flipping pairs of cards. If they happen to match, it is a win for the player who turned them over. Then the cards stay open (or removed from the table). If not, they are flipped back over.

We will be discussing how to create a prototype of such a game with 8 cards and a single player. The computer facilitates the game playing.

To implement the memory game in Lingo, we need to come up first with the data structures that will hold the information of the cards, and with pseudocode that will capture the game's mechanics.

Data Structures

We will use a list to keep track of the cards. We have placed cards in the first several positions of the cast, and for this prototype we will use cards in positions 1-8. Note that there is also a blank card in position 51.

It makes sense the initialization to happen in the preparatory frame or when we click the "New Game" button:

   -- assume 8 cards in sprites 1-8
   totalCards = 8
   -- create a list  of totalCards/2 pairs of cards
   cardList = list()
   cardList = [1,1,2,2,3,3,4,4] -- they need to be shuffled

To start a game we will need to shuffle the cards.

Shuffling the cards

To create the effect of a shuffle, we need to be able to create a random list of pairs of numbers between 1 and half-the-cards on the table. We can start with the non-sorted cardList and then permute their order by repeatedly removing a random one and placing it into a new pile called aftershuffle.

on shuffleCards
   global cardList, totalCards
   aftershuffle = []  -- another way to create an empty list
   repeat while count(cardList) > 0
      pick = random(count(cardList))  -- pick a random card
      symbol = getAt(cardList, pick)  -- find out which is its symbol
      deleteAt cardList, pick         -- remove it from the cardList
      append aftershuffle, symbol     -- and place it in the new list
   end repeat
   cardList = aftershuffle     -- the new list becomes our shuffled cardList
end

After executing shuffleCards, we are ready to start a game!

The code

A card is selected for flipping by clicking on in. So, it makes sense to create a handler on the cast member of the unflipped card (the blank card in position 51). Here is in pseudocode what should happen:

 on mouseUp
   if it is the first card to be flipped then
      flip it -- find out its symbol
      remember its symbol
   else -- if it is the second card flipped in this turn
      flip it -- picking a random symbol
      check whether its symbol matches the previous card's symbol
   end if
end


We need to resolve the following problems:
1. How do we remember the card symbols?
2. How do we find out which symbol was picked?
3. How do we check for match?


1. How do we remember the card symbols?


To remember the card symbols between flips, we can simply use a couple of global variables, called card1 and card2 which are initialized at the beginning of the game to 0 and are reset at the end of every turn. The player can select for card1 and card2 any of the cards we have arranged on the table. It makes sense this to happen in a frame prior to the one playing the game since we may want to replay the game again and again.

on exitFrame me
   global card1, card2, cardList
   card1 = 0 -- no card chosen
   card2 = 0
end
2. How does a random symbol is picked?

To find out which symbol was picked we need to see which blank card the user clicked on, and find the corresponding number from the cardList.

   card1 = the Clickon
   sprite(card1).member = cardList[card1]


3. How do we check for match?


To check for a match between cards we need to see if their symbols match. If they do, fine, give them some feedback via audio to that effect. If not, we need to flip them back and prepare for the next turn. Which means: make card1 and card2 be again 0.

on checkForMatch c1, c2
   global card1, card2
   if c1 = c2 then
      sound(1).queue(member "Match Sound")
      sound(1).play() -- and leave the cards on
   else
      sound(1).queue(member "No Match Sound")
      sound(1).play()
      sprite(card1).member = 51 -- 51 is the blank card
      sprite(card2).member = 51
   end if
end


So, the code on the blank card now is:

on mouseUp me
   global card1, card2, cardList
 
   if card1 = 0 then -- it was the first card of the pair to be clicked
      card1 = the Clickon
      sprite(card1).member = cardList[card1]
   else
      card2 = the ClickOn
      sprite(card2).member = cardList[card2]
      updateStage -- force it to show the second card
 
      checkForMatch cardList[card1], cardList[card2]
      card1 = 0 -- to start another round of guessing
      card2 = 0 
   end if
end

This almost works. Because of the speed of the program flipping cards, the user will not be able to see what the second card is before it is flipped back. (For the first card there is no problem, because we are waiting for the user action.) We need to give the user time to see the second card. We can do that using the delay technique from a previous lecture: by initializing a timer in the beginning of the checkForMatch function


myTimer = the ticks

and in the no-match case wait before flipping back for one second:

delayUntil myTimer+60 -- 60 ticks = 1 second

Like we discussed last time, the delay function could be like that:

on delayUntil timeExpires
   repeat while the ticks < timeExpires 
      nothing
   end repeat 
end
                         
The rest

That's it. Well, almost.
We need to detect when all cards have been flipped and declare the end of the game. How would you do it?

You might want to make it more challenging by having an on-screen timer telling the player how long did it take them to solve the puzzle. See examples from previous code to do that.

ALso, you may want to change the game to use all 50 cards.

You may also need to make this a 2-player game, where players take turns flipping cards and the one with the most pairs wins. That's a little more challenging. How would you do that?

Achnowledgements

The idea and template taken from Gary Rosenzweig's Advanced Lingo for Games

 

 

Maintained By: Takis Metaxas
Last Modified: August 7, 2007