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
|