Building a memory card game

That seems like a lot of code but it really is straightforward.

We’re just defining the two main classes that we need for our game: a card and a grid.

Now, let’s move to our storyboard and controller.

Main storyboard & GameController.

swiftOur Main.

storyboard will look like this:Initially, in the controller, we’ll need to set a new game in the viewDidLoad, including getting the images for our grid.

In our game, that’ll consist of a 4X4 collectionView.

If you’re not familiar with collection views, here’s a good start.

We’ll set up the GameController as the root view controller of our single view app, and in our GameController we’ll have a collectionView that we’re going to reference as a IBOutlet.

Here we are also going to reference a IBAction button onStartGame(), which is the UIButton you can see in our storyboard titled PLAY.

Some hightlights in our controller’s implementation:We’re first initializing our two main objects, the grid: game = MemoryGame(), and our set of cards: cards = [Card]().

We’re setting the game’s initial vars in the viewDidLoad, which is the first method that gets called once our app is running.

The collectionView is initially set to hidden, so the are no cards visible in the screen until the user press PLAY.

Once the user press PLAY, the onStartGame IBAction gets called, and we set our collectionView’s isHidden property to false so it becomes visible.

Every time the user selects an item, the collectionView’s method didSelectItemAt: gets called.

Inside this method we’re calling our own didSelectCard: to pass on the main logic of the game.

Here’s the final implementation for our GameController:Let’s stop at CollectionView’s Delegate Methods for a moment, or protocols for that matter.

ProtocolsWorking with protocols is one of swift’s most fundamental programming patterns.

With protocols you can define rules for a class, structure or enumerator to adopt and implement.

This principle allows us to write decoupled, modular and extensible swift code.

In fact, that’s the pattern we’re already implementing for the collectionView in the GameController.

And now we’re going to make our own.

The syntax will look like this:protocol MemoryGameProtocol { //protocol definition goes here}Since we already know that in the protocol is where we’ll define the rules or instructions for a class to implement, we can now think of what the instructions for our game should be.

We basically need to know 4 things:When to start the game : memoryGameDidStartWhen to show a card downside up: memoryGameShowCardsWhen to show a card upside down: memoryGameHideCardsWhen to end the game: memoryGameDidEndOnce we’ve declared our protocol, we need to implement each four methods in our main class, in this case, our main controller: GameController.

memoryGameDidStartWhen this method gets triggered, it means that the game should start (in our game, this happens when the player taps on the play button).

Here we will simply reload the content by calling collectionView.

reloadData(), being now a set of shuffled cards.

func memoryGameDidStart(_ game: MemoryGame) { collectionView.

reloadData()}memoryGameShowCardsWe’re calling this method from the collectionView’s didSelectItemAt:.

First, it shows the selected card.

Then it checks if we have an unmatched card stored in our cardsShown array (if the cardsShown count is odd).

If we do have an unmatched card, we then compare the card selected with the unmatched card.

If they’re equal, both cards are appended to cardsShown and they remain visible.

If they’re not equal, we remove the unmatched card from the cardsShown list and hide both cards.

memoryGameHideCardsIf cards aren’t equal, this method gets called so they return to a hidden state, shown = false.

memoryGameDidEndWhen this method gets called, it means that all the cards are visible, that we have moved all the initial cards to our cardsShown list: cardsShown.

count = cards.

count, so the game is finished.

This method gets called specifically after we called endGame() to set the isPlaying var to false and from here we then display an alert, letting the user know that the game has finished, and also using that alertController as an indicator for our controller.

When the alert gets dismissed, viewDidDisappear gets called and it resets the game so the user can play again.

These four methods will look like this in our GameController:extension GameController: MemoryGameProtocol { func memoryGameDidStart(_ game: MemoryGame) { collectionView.

reloadData() } func memoryGame(_ game: MemoryGame, showCards cards: [Card]) { for card in cards { guard let index = game.

indexForCard(card) else { continue } let cell = collectionView.

cellForItem( at: IndexPath(item: index, section:0) ) as!.CardCell cell.

showCard(true, animted: true) } } func memoryGame(_ game: MemoryGame, hideCards cards: [Card]) { for card in cards { guard let index = game.

indexForCard(card) else { continue } let cell = collectionView.

cellForItem( at: IndexPath(item: index, section:0) ) as!.CardCell cell.

showCard(false, animted: true) } } func memoryGameDidEnd(_ game: MemoryGame) { let alertController = UIAlertController( title: defaultAlertTitle, message: defaultAlertMessage, preferredStyle: .

alert ) let cancelAction = UIAlertAction( title: "Nah", style: .

cancel) { [weak self] (action) in self?.

collectionView.

isHidden = true } let playAgainAction = UIAlertAction( title: "Dale!", style: .

default) { [weak self] (action) in self?.

collectionView.

isHidden = true self?.

resetGame() } alertController.

addAction(cancelAction) alertController.

addAction(playAgainAction) self.

present(alertController, animated: true) { } resetGame() }}That was indeed a lot of code.

Here’s the fully-functional project so you can clone it and play around with it.

Happy coding!.✌????Xiomara7/MemoryContribute to Memory development by creating an account on GitHub.

github.

com.

. More details

Leave a Reply