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
	    they do not match, 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 (puzzle). The computer
	  facilitates the  playing. 
	To
	  implement the memory game in Lingo, start by downloading memory_game0.dir . 
	  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.  
	
	We
	  will use a list to keep track of the cards. We have placed
	  cards in the first few entries of the cast, and
	  for this prototype we will use cards in positions 1-4.
	  Note that there is  a blank card in position 51 which will serve as the generic card to flip.  
	 It
	  makes sense the initialization to happen  in the
	  preparatory frame or when we click the "New Game" button: 
	
   -- assume 8 blank cards are placed in sprites (channels) 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.  
    
    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-number-of-cards
      on the table.  
    The easiest way would be to scramble them! 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 its symbol is
      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! 
    
    A
      card is selected for flipping by
      clicking
      on in.
      So, it
      makes sense to create a handler only on the cast member
      of the unflipped card (the blank card in position
      51). (Why?) 
    Here is in pseudocode what should happen: 
    
 on mouseUp
   if it is the first card to be flipped then
      flip it -- find out which its symbol is
      remember its symbol
   else -- if it is the second card flipped in this turn
      flip it -- find out which its symbol is
      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? 
     
      
       
      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. 
    
-- Prepare for a new game
on exitFrame me
   global card1, card2
   card1 = 0     -- Note: 0 means "no card chosen yet"
   card2 = 0
   -- Also initialize your data structures as explained above
end 
    
    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                -- Returns the channel number (1-8) of a selected card
   sprite(card1).member = cardList[card1]  -- Array-like code for cardList.getAt(card1) 
     
      
     
      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   -- Play a sound to give feedback
      sound(1).queue(member "Match Sound")
      sound(1).play()        -- and leave the cards on
   else              -- Play a different sound for feedback
      sound(1).queue(member "No Match Sound")
      sound(1).play()
      -- Not a match, turn the cards back to blank
      sprite(card1).member = 51 -- Remember that 51 is the blank card
      sprite(card2).member = 51
   end if
   -- prepare for another round of the game
   card1 = 0
   card2 = 0
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]
      -- anything else?
   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
       by
      initializing a timer       
    
       myTimer = the ticks 
    in the no-match case wait before flipping back for one
      second. (Note: You just introduced a new variable...) 
    Who will check whether the timer is done? The best place to do this done is to put the code for waiting in the game frame. (Having a repeat doing nothing will not work because the optimizing compiler will ignore it. I can hear the compiler saying: "You eventually want it to turn to blank, let me do it for you...")     
    
-- Game frame
on exitFrame me   global card1, card2, cardList, myTimer   waitingTime = 60   -- That is: 1 sec = 60 ticks   if myTimer + waitingTime < the ticks then -- Time passed     if card2 <>0 then checkForMatch cardList[card1], cardList[card2]   end if       go to the frame end
                          
    
That's
      it. Well, almost.  
  - We  may need to detect when all cards have been
    flipped and declare the end of the game. How would
    you do it?
 
  - You may need to try to have a game with 16 cards, how would you do that?
 
  - 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. But not too challenging! 
 
  - You may want to change the game to have 2 levels, easy (as is) and tough (with 16 cards).
 
  - You may want to be able to save a game to finish later. 
 
  - 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
      game idea and images used were taken from Gary Rosenzweig's Advanced
        Lingo for Games 
    
   |