It is time to fix some errors, and the game is done!
Duplicate Click Error
In the code for lesson 7, if the user turns over a card and clicks it again while it is turned up the program registers a match! We can fix that simply by checking to see if cardTwo is in the same spot as cardOne, and if it is, stop and wait for more user events.
'Check to see if the user has already exposed this card.if clickCard=cardOne thenwait
That was easy!
End of Game
There is an additional error in the code from lesson 7. Nothing happens when all cards are removed from the table. The user needs to get a message and have the ability to begin a new game. We've added a flag to indicate that the game is over. The gameWon variable is 0 when a game is in progress.
gameWon=0'flag that is set when all pairs are removed
When the game is over we set the flag to 1.
if score=12then gameWon=1'flag that all pairs are removed
Play Again?
When the game is over, we ask the user if he wants to play again. If he does, we go to the [new] routine. If he doesn't, we disable mouse events and wait. 'We've moved the mouse-button trapping code so that it appears after the [new] label rather than before it 'so a new game automatically restores the trapping of the leftButtonUp event.
'If all pairs have been removed, ask user if he'wants to play again.if gameWon=1then
msg$="You have won in ";turns;" turns. Play again?"confirm msg$;answer$
if answer$="yes"then'start a new gamegoto[new]else'disable mouse event trapping and wait#1.g "when leftButtonUp"endifendifwait
DEMO
See Lesson 1 for QCard DLL and WAV files needed for the demo code.
'new this time
gameWon=0'flag that is set when all pairs are removed[varSetup]
i=0'i will be our counter var in for/next loops
design=1'default design is circles
newIndex=0'used when shuffling
tempCard=0'temp var used when shuffling
clickCard=0'index of current card clicked by userdim card(24,2)'array to hold card info'card(n,1)=index of card in deck'card(n,2)=visible on table? 1=yes, 0=nogosub[fillCardArray]'fill array with card valuesnomainwinWindowWidth=640:WindowHeight=480UpperLeftX=1:UpperLeftY=1menu#1,"&File","&New",[new],"E&xit",[quit]menu#1,"&Card Back Design","&Circles",[circles],"&Blue",[blue],_
"&Red",[red],"&Mountain",[mountain],"&Purple",[purple],"M&usic",[music]graphicbox#1.g,0,0,640,440open"Memory Card Game"for window_nf as#1#1"trapclose [quit]"'get graphicbox handle
hBox=hwnd(#1.g)'open the dllopen"qcard32.dll"fordllas#qc
'initialize the deckCall InitializeDeck hBox
[new]'reset variables and shuffle cards for next try
turns=0: score=0
clickCard=0: gameWon=0
cardOne=0: cardTwo=0
cardOneX=0: cardTwoX=0
cardOneY=0: cardTwoY=0Call SetDefaultValues
Call SetCurrentBack design
'draw a nice background#1.g "down; fill 10 190 225"#1.g "backcolor 10 190 225"'trap mouse clicks:#1.g "setfocus; when leftButtonUp [checkIndex]"gosub[shuffleCards]'set xy location to start deal
x=10:y=2for i =1to24'set status of all cards to 0, which is face downCall SetCardStatus card(i,1),0'deal cardsCall DealCard hBox,card(i,1),x,y
x=x+100if x>510then'move to next row
x=10
y=y+100endifplaywave"card.wav",sync
'pause 100 milliseconds between cardscall Pause 100scannextwait[checkIndex]
clickCard=0:x=0:y=0'reset values
mx=MouseX: my=MouseY'mouse x and y location'Cards are placed in a grid that is 100x100,'so it is easy to determine which card is clicked'by checking mouse position. Card height is about'100, and width is about 80.'Index of clicked card is placed in var called clickCard'and x,y locations are placed in vars called x and y.'MouseY determines row, and MouseX determines column.selectcasecase my<=102'first row
y=2if mx<=90then clickCard=1:x=10if(mx>=110)and(mx<=190)then clickCard=2:x=110if(mx>=210)and(mx<=290)then clickCard=3:x=210if(mx>=310)and(mx<=390)then clickCard=4:x=310if(mx>=410)and(mx<=490)then clickCard=5:x=410if(mx>=510)and(mx<=590)then clickCard=6:x=510case(my>=102)and(my<202)'second row
y=102if mx<=90then clickCard=7:x=10if(mx>=110)and(mx<=190)then clickCard=8:x=110if(mx>=210)and(mx<=290)then clickCard=9:x=210if(mx>=310)and(mx<=390)then clickCard=10:x=310if(mx>=410)and(mx<=490)then clickCard=11:x=410if(mx>=510)and(mx<=590)then clickCard=12:x=510case(my>=202)and(my<302)'third row
y=202if mx<=90then clickCard=13:x=10if(mx>=110)and(mx<=190)then clickCard=14:x=110if(mx>=210)and(mx<=290)then clickCard=15:x=210if(mx>=310)and(mx<=390)then clickCard=16:x=310if(mx>=410)and(mx<=490)then clickCard=17:x=410if(mx>=510)and(mx<=590)then clickCard=18:x=510case(my>=302)and(my<402)'fourth row
y=302if mx<=90then clickCard=19:x=10if(mx>=110)and(mx<=190)then clickCard=20:x=110if(mx>=210)and(mx<=290)then clickCard=21:x=210if(mx>=310)and(mx<=390)then clickCard=22:x=310if(mx>=410)and(mx<=490)then clickCard=23:x=410if(mx>=510)and(mx<=590)then clickCard=24:x=510caseelse
clickCard=0endselectif clickCard=0thenwait'Check to see if the user has already exposed this card.if clickCard=cardOne thenwait'if card is not visible (has been removed), then waitif card(clickCard,2)=0thenwait'remove card to restore tabletopcall RemoveCard hBox, card(clickCard,1)'set status of cards to 1, which is face upCall SetCardStatus card(clickCard,1),1'deal card face upCall DealCard hBox,card(clickCard,1),x,y
gosub[readValue]'If all pairs have been removed, ask user if he'wants to play again.if gameWon=1then
msg$="You have won in ";turns;" turns. Play again?"confirm msg$;answer$
if answer$="yes"then'start a new gamegoto[new]else'disable mouse event trapping and wait#1.g "when leftButtonUp"endifendifwait[readValue]'check whether this is first or second cardif cardOne=0then
cardOne=clickCard
cardOneX=x
cardOneY=y
return'leave first card up and returnelse
cardTwo=clickCard
cardTwoX=x
cardTwoY=y
endif#1.g "when leftButtonUp"'turn off mouse event while pausingcall Pause 2000'2 second pause to view cards#1.g "setfocus; when leftButtonUp [checkIndex]"
oneVal = GetCardValue(card(cardOne,1))
twoVal = GetCardValue(card(cardTwo,1))'ace=1,deuce=2....jack=11,queen=12,king=13
oneSuit = GetCardSuit(card(cardOne,1))
twoSuit = GetCardSuit(card(cardTwo,1))'returns 1=Clubs, 2=Diamonds, 3=Hearts, 4=Spades.'Remove cards from table --'they will be redealt if they don't match.call RemoveCard hBox, card(cardOne,1)call RemoveCard hBox, card(cardTwo,1)
turns=turns+1'See if cards match each other in suit and value.'If they don't match, turn them face down and redeal them.if(oneVal<>twoVal)or(oneSuit<>twoSuit)then'set status of cards to 0, which is face downCall SetCardStatus card(cardOne,1),0Call SetCardStatus card(cardTwo,1),0'deal card face downCall DealCard hBox,card(cardOne,1),cardOneX,cardOneY
Call DealCard hBox,card(cardTwo,1),cardTwoX,cardTwoY
else'If cards match, increment score and don't'replace them on the table.'Set visible to 'off'
card(cardOne,2)=0
card(cardTwo,2)=0
score=score+1endif
cardOne=0: cardTwo=0
cardOneX=0: cardTwoX=0
cardOneY=0: cardTwoY=0'reset for next try
msg$="Turns: ";turns;" Score: ";score
#1.g "place 10 420"#1.g "\" ; msg$; space$(400)if score=12then gameWon=1'flag that all pairs are removedRETURN'setting new card back doesn't restart game,'so new back won't show until new game is started:[circles] design=1:goto[setDesign][blue] design=2:goto[setDesign][red] design=3:goto[setDesign][mountain] design=4:goto[setDesign][purple] design=5:goto[setDesign][music] design=6:goto[setDesign][setDesign]Call SetCurrentBack design
'design can be 1,2,3,4,5,6 for 6 possible designswait[fillCardArray]'fill card array'cards 1 to 52 are in the first deck'cards 53 to 104 are in the second deck'use cards Jack through King in each suit, first deck
card(1,1)=11'jack of clubs
card(2,1)=12'queen
card(3,1)=13'king
card(4,1)=24'jack of diamonds
card(5,1)=25'queen
card(6,1)=26'king
card(7,1)=37'jack of hearts
card(8,1)=38'queen
card(9,1)=39'king
card(10,1)=50'jack of spades
card(11,1)=51'queen
card(12,1)=52'king'now use second deck, to fill second half of arrayfor i =1to12
card(i+12,1)=card(i,1)+52nextRETURN[shuffleCards]'first set all cards as visible, card(n,2)=1for i =1to24
card(i,2)=1nextplaywave"shuffle.wav",async
'now shuffle cardsfor i =1to24
newIndex=int(rnd(0)*24)+1
tempCard=card(i,1)'temp var to allow switching values
card(i,1)=card(newIndex,1)'this index now contains value from random index
card(newIndex,1)=tempCard 'random index now contains value from other index'now card(i,1) has switched values with a random card in the arraynextplaywave"shuffle.wav",sync
RETURN[quit]close#qc:close#1:end'''''''''''''''''''''subs and functions:Sub Pause ms
'pause ms number of millisecondscalldll#kernel32,"Sleep",_
ms aslong, re asvoidEndSubFunction GetCardSuit(nC)'returns 1=Clubs, 2=Diamonds, 3=Hearts, 4=Spades.calldll#qc,"GetCardSuit",nC aslong,_
GetCardSuit aslongEndFunctionFunction GetCardValue(nC)'ace=1,deuce=2....jack=11,queen=12,king=13calldll#qc,"GetCardValue",nC aslong,_
GetCardValue aslongEndFunctionSub InitializeDeck hndle
calldll#qc,"InitializeDeck",_
hndle asulong,r aslongEndSubSub SetCardStatus nC,face
'nC is number of card - 1-52 in first deck and'53-104 in second deck, if used'face: 0=facedown,1=faceupcalldll#qc,"SetCardStatus",nC aslong,_
face aslong,r asvoidEndSubSub DealCard hndle,nC,x,y
'places card on window whose handle is hndle at x,y'nC is number of card - 1-52 in first deck and'53-104 in second deck, if usedcalldll#qc,"DealCard",hndle asulong,nC aslong,_
x aslong,y aslong,r asvoidEndSubSub SetCurrentBack nV
'nV can be 1,2,3,4,5,6 for 6 possible designscalldll#qc,"SetCurrentBack",nV aslong,r asvoidEndSubSub SetDefaultValues
'reset all card properties back to their default values.calldll#qc,"SetDefaultValues",r asvoidEndSubSub RemoveCard hndle,nC
'removes a card from screen that was'drawn with DealCard, replacing screen backgroundcalldll#qc,"RemoveCard",hndle asulong,_
nC aslong,r asvoidEndSub
QCard DLL Lesson 8
Lesson 7-
QCard DLL Lesson 8 | Finishing the Memory Card Game | Duplicate Click Error | End of Game | Play Again? | DEMO
See Lesson 1 for QCard DLL and WAV files needed for the demo code.
Finishing the Memory Card Game
It is time to fix some errors, and the game is done!
Duplicate Click Error
In the code for lesson 7, if the user turns over a card and clicks it again while it is turned up the program registers a match! We can fix that simply by checking to see if cardTwo is in the same spot as cardOne, and if it is, stop and wait for more user events.
That was easy!
End of Game
There is an additional error in the code from lesson 7. Nothing happens when all cards are removed from the table. The user needs to get a message and have the ability to begin a new game. We've added a flag to indicate that the game is over. The gameWon variable is 0 when a game is in progress.
When the game is over we set the flag to 1.
Play Again?
When the game is over, we ask the user if he wants to play again. If he does, we go to the [new] routine. If he doesn't, we disable mouse events and wait. 'We've moved the mouse-button trapping code so that it appears after the [new] label rather than before it 'so a new game automatically restores the trapping of the leftButtonUp event.
DEMO
See Lesson 1 for QCard DLL and WAV files needed for the demo code.QCard DLL Lesson 8 | Finishing the Memory Card Game | Duplicate Click Error | End of Game | Play Again? | DEMO
Lesson 7