forked from pharo-graphics/Tutorials
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New version to check if the old is still working. Redoing everything …
…following the booklet (to be updated).
- Loading branch information
Showing
9 changed files
with
507 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
Class { | ||
#name : #BaselineOfMemory, | ||
#superclass : #BaselineOf, | ||
#category : #BaselineOfMemory | ||
} | ||
|
||
{ #category : #baselines } | ||
BaselineOfMemory >> baseline: spec [ | ||
<baseline> | ||
|
||
spec for: #'common' do: [ | ||
spec package: #'Bloc-Memory' ] | ||
|
||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Package { #name : #BaselineOfMemory } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
" | ||
I am a card model that can be flipped to show its back or face. | ||
When card is flipped on the face a player should see a symbol that is used to compare two cards. | ||
!! Examples: | ||
[[[ | ||
| cardModel | | ||
cardModel := MGCard new symbol: $a. | ||
cardModel flip. | ||
cardModel disappear | ||
]]] | ||
" | ||
Class { | ||
#name : #MGCard, | ||
#superclass : #Object, | ||
#instVars : [ | ||
'symbol', | ||
'flipped', | ||
'announcer' | ||
], | ||
#category : #'Bloc-Memory-Model' | ||
} | ||
|
||
{ #category : #accessing } | ||
MGCard >> announcer [ | ||
"Return my announcer that is used to notify my observers" | ||
|
||
^ announcer ifNil: [ announcer := Announcer new ] | ||
] | ||
|
||
{ #category : #actions } | ||
MGCard >> disappear [ | ||
"Ask card to disapper" | ||
|
||
self notifyDisappear | ||
] | ||
|
||
{ #category : #actions } | ||
MGCard >> flip [ | ||
"Flip the card on the other side (toggle flipped state)" | ||
|
||
flipped := flipped not. | ||
self notifyFlipped | ||
] | ||
|
||
{ #category : #initialization } | ||
MGCard >> initialize [ | ||
super initialize. | ||
flipped := false | ||
] | ||
|
||
{ #category : #testing } | ||
MGCard >> isFlipped [ | ||
"Return true if card is flipped and its face (symbol) is visible, false otherwise" | ||
|
||
^ flipped | ||
] | ||
|
||
{ #category : #notifying } | ||
MGCard >> notifyDisappear [ | ||
"Notify all observers that I disappeared from the game" | ||
|
||
self announcer announce: MGCardDisappearAnnouncement new | ||
] | ||
|
||
{ #category : #notifying } | ||
MGCard >> notifyFlipped [ | ||
"Notify all observers that my flipped state was changed (from flipped to not or the other way around)" | ||
|
||
self announcer announce: MGCardFlippedAnnouncement new | ||
] | ||
|
||
{ #category : #printing } | ||
MGCard >> printOn: aStream [ | ||
aStream | ||
nextPutAll: 'Card'; | ||
nextPut: Character space; | ||
nextPut: $(; | ||
nextPut: self symbol; | ||
nextPut: $) | ||
] | ||
|
||
{ #category : #accessing } | ||
MGCard >> symbol [ | ||
"Return a symbol that should be displayed when card is flipped and face is visible" | ||
|
||
^ symbol | ||
] | ||
|
||
{ #category : #accessing } | ||
MGCard >> symbol: aCharacter [ | ||
"Initialize the card with a given symbol as a character" | ||
|
||
symbol := aCharacter | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
" | ||
Is sent by ==MgdCardModel== after the card is removed from the ==MgdGameModel== | ||
" | ||
Class { | ||
#name : #MGCardDisappearAnnouncement, | ||
#superclass : #Announcement, | ||
#category : #'Bloc-Memory-Events' | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
" | ||
Is sent by ==MgdCardModel== after the card is flipped | ||
" | ||
Class { | ||
#name : #MGCardFlippedAnnouncement, | ||
#superclass : #Announcement, | ||
#category : #'Bloc-Memory-Events' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
" | ||
I am a memory game model | ||
" | ||
Class { | ||
#name : #MGGame, | ||
#superclass : #Object, | ||
#instVars : [ | ||
'availableCards', | ||
'chosenCards' | ||
], | ||
#category : #'Bloc-Memory-Model' | ||
} | ||
|
||
{ #category : #factory } | ||
MGGame class >> withChinese [ | ||
^ self new initializeForSymbols: '为从公家里地个时' | ||
] | ||
|
||
{ #category : #factory } | ||
MGGame class >> withEmoji [ | ||
^ self new initializeForSymbols: '💰🏡🎅🍪🍕🚀😸🙈' | ||
] | ||
|
||
{ #category : #factory } | ||
MGGame class >> withNumbers [ | ||
^ self new initializeForSymbols: '12345678' | ||
] | ||
|
||
{ #category : #adding } | ||
MGGame >> addCard: aCard [ | ||
"Add card to the list of available cards" | ||
|
||
availableCards add: aCard | ||
] | ||
|
||
{ #category : #accessing } | ||
MGGame >> availableCards [ | ||
|
||
^ availableCards | ||
] | ||
|
||
{ #category : #accessing } | ||
MGGame >> cardsCount [ | ||
"Return how many cards there should be." | ||
|
||
^ self gridSize * self gridSize | ||
] | ||
|
||
{ #category : #actions } | ||
MGGame >> chooseCard: aCard [ | ||
"This is the main logic of the game. | ||
The user pick a card, if this is a new one it is added to the chosen ones, | ||
then flipped. At this point the game check if all the cards have been chosen and | ||
if they are good, remove them. | ||
Else the cards are flipped back and remove from the chosen list." | ||
|
||
(self chosenCards includes: aCard) | ||
ifTrue: [ ^ self ]. | ||
self chosenCards add: aCard. | ||
aCard flip. | ||
self shouldCompleteStep | ||
ifTrue: [ ^ self completeStep ]. | ||
self shouldResetStep | ||
ifTrue: [ self resetStep ] | ||
] | ||
|
||
{ #category : #testing } | ||
MGGame >> chosenCardMatch [ | ||
"Return whether the chosen cards match." | ||
"The implementation is handling the fact that we could want to have a game where more than two matches are needed e.g., three cards of the same symbol." | ||
|
||
| firstCard | | ||
firstCard := self chosenCards first. | ||
^ self chosenCards allSatisfy: [ :aCard | | ||
aCard isFlipped and: [ firstCard symbol = aCard symbol ] ] | ||
] | ||
|
||
{ #category : #accessing } | ||
MGGame >> chosenCards [ | ||
^ chosenCards | ||
] | ||
|
||
{ #category : #actions } | ||
MGGame >> completeStep [ | ||
"The player found the same cards so the step is complete. The cards should be removed from the board." | ||
|
||
self chosenCards | ||
do: [ :aCard | aCard disappear ]; | ||
removeAll. | ||
] | ||
|
||
{ #category : #accessing } | ||
MGGame >> gridSize [ | ||
"Return grid size, total amount of card is gridSize^2" | ||
|
||
^ 4 | ||
] | ||
|
||
{ #category : #initialization } | ||
MGGame >> initialize [ | ||
super initialize. | ||
|
||
availableCards := OrderedCollection new. | ||
chosenCards := OrderedCollection new | ||
] | ||
|
||
{ #category : #initialization } | ||
MGGame >> initializeForSymbols: aCollectionOfCharacters [ | ||
|
||
"Initialize game model with the cards that are represented by character symbols taken from a given | ||
collection of symbols. | ||
Note, amount of characters must correspond to amount of possible card combinations | ||
which is in fact = (total card count / how many card to match). | ||
So, if grid size is 4, then total card count is 4^2 = 16. If player should match 2 cards, | ||
then collection size must be 16 / 2 = 8" | ||
|
||
aCollectionOfCharacters size = (self cardsCount / self matchesCount) | ||
ifFalse: [ self error: 'Amount of characters must be equal to possible all combinations' ]. | ||
|
||
availableCards := (aCollectionOfCharacters asArray | ||
collect: [ :aSymbol | | ||
(1 to: self matchesCount) collect: [ :i | | ||
MGCard new symbol: aSymbol ] ] ) flattened shuffled asOrderedCollection | ||
] | ||
|
||
{ #category : #accessing } | ||
MGGame >> matchesCount [ | ||
"How many chosen cards should match to disappear" | ||
|
||
^ 2 | ||
] | ||
|
||
{ #category : #actions } | ||
MGGame >> resetStep [ | ||
"" | ||
|
||
| lastCard | | ||
lastCard := self chosenCards last. | ||
self chosenCards | ||
allButLastDo: [ :aCard | aCard flip ]; | ||
removeAll; | ||
add: lastCard | ||
] | ||
|
||
{ #category : #testing } | ||
MGGame >> shouldCompleteStep [ | ||
"Return true if current step should be completed, false otherwise. | ||
According to game rules step is done when all chosen cards match | ||
and their amount corresponds to a specific number (#matchesCount)" | ||
|
||
^ self chosenCards size = self matchesCount | ||
and: [ self chosenCardMatch ] | ||
] | ||
|
||
{ #category : #testing } | ||
MGGame >> shouldResetStep [ | ||
^ self chosenCards size > self matchesCount | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
" | ||
| board space | | ||
board := MGGameElement example. | ||
space := BlSpace new. | ||
space extent: 420@420. | ||
space addChild: board. | ||
space show. | ||
{ board . space } inspect | ||
" | ||
Class { | ||
#name : #MGGameElement, | ||
#superclass : #BlElement, | ||
#instVars : [ | ||
'memoryGame' | ||
], | ||
#category : #'Bloc-Memory-Elements' | ||
} | ||
|
||
{ #category : #example } | ||
MGGameElement class >> example [ | ||
"self example" | ||
<example> | ||
|
||
| game board | | ||
game := MGGame withNumbers. | ||
board := MGGameElement new. | ||
board memoryGame: game. | ||
^ board | ||
] | ||
|
||
{ #category : #initialization } | ||
MGGameElement >> initialize [ | ||
super initialize. | ||
self layout: BlGridLayout horizontal. | ||
] | ||
|
||
{ #category : #accessing } | ||
MGGameElement >> memoryGame [ | ||
^ memoryGame | ||
] | ||
|
||
{ #category : #accessing } | ||
MGGameElement >> memoryGame: anObject [ | ||
memoryGame := anObject. | ||
memoryGame availableCards | ||
do: [ :aCard | self addChild: (self newCardElement card: aCard) ] | ||
] | ||
|
||
{ #category : #accessing } | ||
MGGameElement >> newCardElement [ | ||
^ MGCardElement new | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Package { #name : #'Bloc-Memory' } |