斯坦福iOS 7公開課-Assignment 1

Task1

Follow the detailed instructions in the lecture slides (separate document) to build and run Matchismo in the iPhone Simulator in Xcode 5. Do not proceed to the next steps unless your card flips back and forth as expected and builds without warnings or errors.git

跟着視屏Demo作便可,白鬍子爺爺講得超級詳細,有疑問的地方在Lecture#2的Slide裏面基本均可以找到答案。github

Task2

Be sure to include all the code for the four classes shown in the first two lectures: Card, Deck, PlayingCard and PlayingCardDeck. You must type this code in (e.g., do not copy and paste it from somewhere). The whole point of this Required Task is to gain experience editing code in Xcode and to get used to Objective-C syntax.less

把Lecture#1,2裏面涉及到的四個類Card, Deck, PlayingCard, PlayingCardDeck敲進去,必定要本身敲進去,由於一般狀況是,一邊敲一邊問題就來了。dom

Task3

Add a private property of type Deck * to the CardGameViewController.ide

從這裏開始就是做業要求獨立完成的部分了,題目說得很清楚字兒也極短,要敲的代碼也不多,可是這裏有些須要理解的部分。

首先仍是在XxxViewController.m裏聲明一個Deck屬性,別忘了先import在Task2裏寫好的PlayingCard.h。函數

@property (strong,nonatomic) Deck *myDeck;

咱們聲明這個Deck私有屬性的目的是爲了初始化一張有52張牌的桌子(好彆扭的說法==),可是其實咱們能夠看到咱們以前寫的init的方法是在PlayingDeck裏面的。這裏白鬍子大叔還有Hint針對這個問題呢。優化

Even though the type of the property you must add is required to be a Deck (not PlayingCardDeck) you’ll obviously have to lazily instantiate it using a PlayingCardDeck. This is perfectly legal in object-oriented programming because a PlayingCardDeck inherits from Deck and thus it 「is a」 Deck. If you are confused by this concept in object-oriented programming, this course may be rather difficult for you.ui

好吧,我不會認可我最開始就是自做聰明地聲明的PlayingCard的╮(╯▽╰)╭,結果被赤裸裸地鄙視了==其實這個呢,咱們作完Task4就能夠看出一些端倪了。this

Task4

Use lazy instantiation to allocate and initialize this property (in the property’s getter)atom

so that it starts off with a full deck of PlayingCards.

添加代碼以下:

-(Deck *)myDeck
{
    if (!_myDeck) {
     _myDeck = [[PlayingDeck alloc]init];
    }
return _myDeck;
}

首先這裏用到了傳說中lazy instantiation(惰性初始化),咱們以前在Deck.m中初始化Card的時候就用到了這個;其次,這裏的_myDeck是用PlayingDeck初始化的!因此以前擔憂的Deck裏面沒有override的init方法是白費功夫了。不過爲啥這麼寫,跟小夥伴討論的結果是用了多態

Task5

Matchismo so far only displays the A♣ over and over. Fix Matchismo so that each time the card is flipped face up, it displays a different random card drawn from the
Deck property you’ve created above. In other words, Matchismo should flip through an entire deck of playing cards in random order, showing each card one at a time.

這個問題也不難,經過前面的任務,咱們已經有了「一張有52張牌的桌子」,而在Deck.h中白鬍子大叔已經帶咱們實現了一個drawRandomCard的函數,那麼只要在每次按下button的時候,咱們調用一下這個函數就實現了從牌堆裏隨機取出一張牌(注意已經取出了),而後顯示card的內容直接用contents這個函數。

  • (IBAction)touchCardButton:(UIButton *)sender {
    ……
    else{

    Card *myCard = [self.myDeck drawRandomCard];

    ……

    [sender setTitle:[myCard contents] forState:UIControlStateNormal];

    }

    self.flipCount++;//both call setter and getter

    }

這個Task主要的問題在於,這下子初始的狀況要顯示牌的背面。這個不是能在touchCardButton裏實現,由於咱們的touchCardButton監聽的一個action,這裏須要的是一個outlet。

首先,按住ctrl再把button拖入@implemention中,在connection裏面選outlet,隨便輸入一個名字好比cardButton,這樣咱們又聲明瞭一個property;而後在以前白鬍子大叔「忽悠」咱們刪掉的函數viewDidLoad中添加下面的代碼:

-(void)viewDidLoad{
    [super viewDidLoad];
    [self touchCardButton:self.cardButton];
    self.flipCount = 0;
}

前兩句代碼我也不是特別明白。對於第一句,其實在PlayingDeck裏面實現init的時候咱們也寫過相似的:

self = [super init]

我的感受是一個道理,在那裏白鬍子大叔解釋不少:

This is the ONLY time you would ever assign something to self

But we have to check to see if our superclass can initialize itself. The assignment to self is a bit of protection against our trying to continue to initialize ourselves if our superclass couldn’t initialize. Just always do this and don’t worry about it too much.
Sending a message to super is how we send a message to ourselves, but use our superclass’s implementation instead of our own.
Standard object-oriented stuff.

而後只要先在button上隨便寫點東西,根據咱們的touchCardButton函數,就會進入到else裏面顯示card的背面。

Task6

Do not break the existing functionality in Matchismo (e.g. the Flips counter should still continue to count flips).

這沒什麼好說的了╮(╯▽╰)╭

補充

在Lesson3裏,白鬍子大叔有講此次做業的答案,不過他說這是惟一一次講答案了╮(╯▽╰)╭
他主要優化了三個地方,一個是以前提到的,初始時顯示牌的背面,第二個是沒有牌的時候,要提示用戶沒牌了,第三個是設置的flipCount一直計數也是很是討厭的。

  • 優化1:
    大叔作的沒那麼複雜,就是把字符串刪掉,背景設置成了cardback便可。看來我想多了,不過這也的確不符合task6的精神

  • 優化2:
    以前的寫的代碼在沒牌的時候會用下面的代碼把button都移除了,點到最後忽然沒了仍是怪瘮人的,主要萬一還想幹點別的也無法作了,因而仍是設置成牌翻完了就一直顯示爲背面好了。

[sender removeFromSuperview];
  • 優化3:
    這個也很簡單哇,把self.flipCount++移到if(myCard)裏面便可。

-(IBAction)touchCardButton:(UIButton *)sender {
    if ([sender.currentTitle length]) {
    [sender setBackgroundImage:[UIImage imageNamed:@"cardback"]  forState:UIControlStateNormal];
    [sender setTitle:@"" forState:UIControlStateNormal];
    }
    else{
    Card *myCard = [self.myDeck drawRandomCard];
    if (myCard) {
        [sender setBackgroundImage:[UIImage imageNamed:@"cardfront"] forState:UIControlStateNormal];
        [sender setTitle:[myCard contents] forState:UIControlStateNormal];
        self.flipCount++;//both call setter and getter
    }
    /*
    else{
         [sender removeFromSuperview];
    }*/
    } 
    }

效果圖

完整代碼

圖片描述

初學者理解不當之處,求指正,謝謝。

-EOF-

相關文章
相關標籤/搜索