Implementing the Memory Game model logic

Game Logic

Next, we need Game>>#chooseCard:, a method that is called when a user selects a card. This method is actually the most complex method of the model and implements the main logic of the game. First, the method makes sure that the chosen card is not already selected. This could happen if a player by chance clicks on a card more than once. Next, the card is flipped by sending it the message Card>>#flip.

If two cards are flipped and they match, they are made to disappear. If they don't match, when a third card is chosen to flip, the first two will be flipped back.

"protocol: #actions"

Game >> chooseCard: aCard
	(self chosenCards includes: aCard) 
		ifTrue: [ ^ self ].
	self chosenCards add: aCard.
	aCard flip.
	self shouldCompleteStep
		ifTrue: [ ^ self completeStep ].
	self shouldResetStep
		ifTrue: [ self resetStep ]

"protocol: #testing"

Game >> shouldCompleteStep
	^ self chosenCards size = self matchesCount
		and: [ self chosenCardMatch ]

"protocol: #testing"

Game >> chosenCardMatch
	| firstCard |
	firstCard := self chosenCards first.
	^ self chosenCards allSatisfy: [ :aCard | 
		aCard isFlipped and: [ firstCard symbol = aCard symbol ] ]

"protocol: #private"

Game >> completeStep
	self chosenCards 
		do: [ :aCard | aCard disappear ];
		removeAll.

"protocol: #testing"

Game >> shouldResetStep 
	^ self chosenCards size > self matchesCount

"protocol: #private"

Game >> resetStep
	| lastCard |
	lastCard := self chosenCards last.
	self chosenCards 
		allButLastDo: [ :aCard | aCard flip ];
		removeAll;
		add: lastCard
  

Let's play with the Game>>#chooseCard: method. By executing the following script, we flip a random card (face side visible):

aGame := Game numbers.
aGame chooseCard: aGame availableCards atRandom
  

By executing the following snippet, we will obtain a game state where two first cards are flipped:

aGame := Game numbers.
aGame chooseCard: aGame availableCards first.
aGame chooseCard: aGame availableCards second
  

And finally, by executing the next snippet, we will obtain a game state where the first two cards are flipped back (back-side) and third card is flipped (face side is visible):

aGame := Game numbers.
aGame chooseCard: aGame availableCards first.
aGame chooseCard: aGame availableCards second.
aGame chooseCard: aGame availableCards third
  

Ready

Next, we implement a Bloc widget: Building the Memory Game graphical elements with Bloc.

Links to Pages containing missing references - allowed failures to allow references to missing classes and methods in the page.