IOS development of Stanford University open class summary (three): the card pairing game Demo

This class of knowledge content is not much, mainly is a continuation of a lesson over the single card games (see: Stanford University iOS open class summary (two): Demo card), a card will be extended to a multi card and match and scoring game.

Although the content of this lesson is simple, but it is very important, the instructor stressed the MVC design principles and the actual application of the code, this article on the specific code Demo to explain the knowledge points mentioned in this lesson.

Design requirements


  • Show multiple cards, click on any one card can flop.
  • Two cards are displayed after the front can be matched: color match was 1 points; the number of matches to get a score of 4, after the match, the card is not allowed to switch to the state of the two. Do not match the deduction of 2 points. Every time you lose a minute.
  • Each flop to update scores.

Design sketch´╝Ü


IOS development of Stanford University open class summary (three): the card pairing game Demo
left: initial interface; right: game interface

Important code segments and knowledge points


Model class: CardMatchingGame

1 set read-only attributes on the common interface

//CardMatchingGame.h @property (nonatomic, readonly) NSInteger score; //CardMatchingGame.m @property (nonatomic, readwrite) NSInteger score;

In the.H file will be set to read-only attributes, and in the.M file to set the property to read and write in order to calculate the internal. Reason: you do not want other classes to change this property, you can only get this property. Popular point: “you take me to give you a good score is good, you can not change it!”

2 specify initializers: Designated initializer

- (instancetype) initWithCardCount: (NSUInteger) count usingDeck: (Deck * deck) {self = [super init]; if (self) {for (int i = 0; I < count; i++) {Card *card = [deck drawRandomCard]; if (card) {[self.cards addObject:card}else{; self = nil; break;} return self}}};

Sometimes, when we need to instantiate the class in the request object holds some data, it needs to design the specified initializers, because the original initialization method – (instancetype) init method is unable to let the instance object with non null data (after initialization, basic data type attribute object attributes =0; =nil). In this code, the model class through the number of count and a bunch of cards in the deck to get their own holdings of self.cards. A: want to have 52 cards from a heap from 12 cards as a pack of cards yourself will be set to Deck for array with 52 cards; and set the count to 12.

3 set constants

#define MISMATCH_PENALTY / / 2 simply replace data types do not have
Static const int MISMATCH_PENALTY = 2; / / non simple replacement, has a data type

Controller class: CardMathcingGameViewController


1 receive the click event from View and update UI

Receive the user's click event / * * * * * @param sender click on the button object * / - (IBAction) touchCardButton: (UIButton * sender) {//1. find the click interface button in the index NSInteger cardIndex = [self.cardButtons indexOfObject:sender]; //2. find the same card data in the index model, and determine whether the matching score [self.game chooseCardAtIndex: cardIndex]; //3. update UI [self updateUI];} / * * * * / update UI - (void) updateUI {//1. update all brand view on the surface of for (UIButton *cardButton in self.cardButtons) {//1.1 find a card in the interface (in accordance with the enumeration order) NSInteger cardIndex = [self.cardButtons indexOfObject:cardButton]; //1.2 to find the corresponding model in the number of cards According to Card *card = [self.game cardAtIndex:cardIndex]; //1.3 according to the data update cards UI and click [cardButton setTitle:[self titleForCard:card] forState:UIControlStateNormal] [cardButton setBackgroundImage: [self backgroundImageForCard:card]; forState:UIControlStateNormal]; cardButton.enabled = card.isMatched;}! //2. self.scoreLabel.text = [NSString stringWithFormat:@ update fraction "Score:%ld" (long, self.game.score]);}

Here, we can easily see the workflow of MVC: in the View click event occurred and notify the Controller. Controller told Model that a click. Model updates itself according to the click event, and then updates itself to Controller. Controller updates the UI according to the updated model.

Here I have a picture of their own painting, a little funny force, hide his face, not as happy as Lele lele

IOS development of Stanford University open class summary (three): the card pairing game Demo
MVC flow chart.Png

Scattered knowledge points


1 in the array to its containing the object to return to its serial number

NSInteger cardIndex = [self.cardButtons indexOfObject:cardButton];

2 find the first element in the array

Should use: *otherCard = PlayingCard / / [otherCards / / firstObject]; should not use *otherCard: PlayingCard = otherCards[0]; / / should not use: PlayingCard *otherCard = [otherCards objectAtIndex:0];

The first case should be used.
because if the array is empty, it is not possible to send a message to the nil if the first case is used to return nil.
but if you use the latter two methods, once the array is empty, it will immediately cause the program to crash! The same applies to the last element of the array.
found the last element in the array: PlayingCard *otherCard = [otherCards lastObject];

3 contains an element in the array

If ([PlayingCard ValidSuits] containsObject:suit]) {_suit = suit;}

ContainsObject: is a NSArray method that returns a Boolean value that determines whether an element is contained.

4 JPG format image read

- (UIImage) backgroundImageForCard: (Card * card) {/ / default is PNG, if JPG need to add the.Jpg suffix return [UIImage imageNamed:card.isChosen? @ @ "cardFront.jpg": "CardBack.png"}];

If you use the imageNamed: method, only the incoming JPG format file name is unable to show pictures, should be introduced into the suffix.Jpg splicing can Oh ~ and under the same conditions, to display the PNG format picture does not require the addition of the suffix.

Last words:


If a small partner wants to get this Demo code please do not hesitate to comment on the comments can be.
and very welcome to the author of the code and style of writing out valuable comments and suggestions

In this paper, the original author, for reprint, please negotiate with me in advance!

2016.7.12 day update:


I have so far finishing all Demo (second classes to tenth classes) into my GitHub warehouse. English version is divided into English and Chinese version of the notes (English notes to a little less, Hei hei) want to be able to download a small partner ~ if you do not know how to download a small partner please contact me ~!

This article has been printed on the copyright, for reprint please visit the copyright print. Forty-eight million four hundred and twenty-two thousand nine hundred and twenty-eight

Obtain authorization