Info

Programmer by day, artist by night

Attached is the solution to the Assignment 2: Matchismo 2 (3-Card Matching Game) from the course “Developing iOS7 Apps for iPhone and iPad (Fall 2013)” by Stanford University (available in iTunes). The attached solution is not limited to a 2-card or 3-card matching game. The same method can be used for n-cards.

The solution addresses all the required tasks in the Assignment. The scoring mechanism implemented is a very simplified approach based on what was already shown in the lectures. While the iOS related tasks were easy to implement, the 3-card matching logic took some thought. There are obviously many approaches to matching a 3-card game. The solution attached is based on the CardMatchingGame model.

The model already stores the chosen and matched states of each card. While it may be tempting to create separate procedures to loop through the number of cards being played and matched, this is not required as the model already holds that information. All we need to do is simply to ask it.

The implementation also adds 2 features not required in the assignment. It presents the user with an alert (UIAlertView) when re-dealing the cards. This was easy to implement via UIAlertViewDelegate. A quick jump to the documentation shows how to do this. The other feature that was added was via the method – (void)shouldDisableGame. This disables the last remaining cards from being clicked if they cannot be matched.

A quick video demonstrating the solution in action.

Please download the attachment for full details – it contains the Xcode 5 project for Matchismo. Just unzip the file matchismo.zip and open Matchismo.xcodeproj

Download Solution to Assignment 2: Matchismo 2 (3-Card Matching Game)

The core matching logic is pasted below with inline code comments:

- (void)chooseCardAtIndex:(NSUInteger)index
{
    Card *card = [self cardAtIndex:index];
    
    if (!card.isMatched) {
        if (card.isChosen) {
            card.chosen = NO;
            self.status = @"";
        } else {
            // match against other cards
            
            // First we store the cards that are chosen and not matched in currentChosenCards
            NSMutableArray *currentChosenCards = [[NSMutableArray alloc] init];
            NSMutableString *statusCurrentChosenCards = [[NSMutableString alloc] init];
            for (Card *otherCard in self.cards) {
                if (otherCard.isChosen && !otherCard.isMatched) {
                    [currentChosenCards addObject:otherCard];
                    [statusCurrentChosenCards appendFormat:@"%@ ", otherCard.contents];
                }
            }
            if ([currentChosenCards count]) {
                self.status = [[NSString stringWithFormat:@"Chose %@ to match with: ", card.contents] stringByAppendingString:statusCurrentChosenCards];
            } else {
                self.status = [NSString stringWithFormat:@"Chose %@", card.contents];
            }

            
            // The model is already tracking how many cards are currently chosen and not matched
            // So all we need to do is match that count with the number of cards we are playing with
            // We do a -1 because currentChosenCards doesn't include the card that was just clicked
            if ([currentChosenCards count] == self.numberOfCardsToPlayWith-1) {
                int matchScore = [card match:currentChosenCards];
                if (matchScore) {
                    self.score += matchScore * MATCH_BONUS;
                    for (Card *otherCard in currentChosenCards) {
                        otherCard.matched = YES;
                    }
                    card.matched = YES;
                    self.status = [[NSString stringWithFormat:@"Scored: %d. Match found for: %@ ", matchScore * MATCH_BONUS, card.contents] stringByAppendingString:statusCurrentChosenCards];
                } else {
                    self.score -= MISMATCH_PENALTY;
                    for (Card *otherCard in currentChosenCards) {
                        otherCard.chosen = NO;
                    }
                    self.status = [[NSString stringWithFormat:@"Penalty: %d. No match found for: %@ ", MISMATCH_PENALTY, card.contents] stringByAppendingString:statusCurrentChosenCards];
                }
            }
        
            self.score -= COST_TO_CHOOSE;
            card.chosen = YES;
        }
    }
    
    // This is not part of the assignment. It's just a nice way to end the game.
    // If the last remaning cards do not match, the game should freeze those cards
    // from being clicked and end the game.
    [self shouldDisableGame];
}

Comments

12 Comments

Post a comment
  1. Sean #
    March 1, 2015

    How can “if (otherCard.isChosen && !otherCard.isMatched)” evaluate to TRUE? Because we never set otherCard.isChosen to YES. So it should be always FALSE/NO right ??

    • March 2, 2015

      It’s been a while since I worked on this project, but the state of otherCard.isChosen will get set to YES as soon as it’s flipped to face it’s front.

  2. Aza #
    January 29, 2016

    could you send zip-file, please, because, i think it’s deleted now?

  3. Mo #
    February 20, 2016

    In PlayingCard.h we do we write these as a class utility? isn’t it better to write it as a property and then give values to the array?

    +(NSArray *) validSuits
    {
    return @[@”♥”, @”♦”, @”♠”,@”♣”];
    }

    + (NSArray *)rankStrings
    {
    return @[@” “,@”A”,@”2″,@”3″,@”4″,@”5″,@”6″,@”7″,@”8″,@”9″,@”10″,@”J”,@”Q”,@”K”];

    }

    • February 20, 2016

      Valid suits and available ranks are the same for all playing cards, so it doesn’t make sense to store them as object properties. Since there are no equivalent class level @property in Objective-C, we store them as class methods. Then again, @properties are just syntactic sugars, behind the scenes they are implemented as object methods. For more, please see: http://stackoverflow.com/questions/695980/how-do-i-declare-class-level-properties-in-objective-c

      • Mo #
        February 20, 2016

        Thanks for prompt reply.
        Also in deck can’t we just import Playing card instead? This would almost make PlayingCardDeck class useless and better to understand.

      • February 22, 2016

        True 🙂 But the Professor was aiming more towards abstraction by creating very generalized versions Card and Deck classes. So that in the future, Deck can be used to create some other collection of cards (other than playing cards).

        Which actually does become a requirement in Assignment 3, where he asks us to implement a Set-Card Matching Game in addition to the current Playing Cards.

  4. Mo #
    February 22, 2016

    Thanks again for your prompt reply sensei!
    I see what you are saying.

    If I finish this course and probably after that do the iOS 8 ( swift) course of Stanford, would I also need to read iOS Programming: The Big Nerd Ranch Guide or that doesn’t cover anything extra to the videos of iTunes U courses?

    I want to be able to learn and do 2-3 real but simple apps and put them on my resume…and find a job. :]
    // Sorry I had to post here, your recommended books page didn’t have a comment section, nor I was able to find any better to contact you.

    • February 22, 2016

      Sure no problem 🙂 And thank you for reading the blog. I think that the Stanford courses and assignments can be hard sometimes because they were after all aimed for students who are collaborating in a real class-room environment, with ready-access to the Professor and Teaching Assistants. Nonetheless the lectures are indeed chock full of gems and reflect Paul Hegarty’s rich experience in the field.

      Based on my own personal experience, I would recommend the following (for faster results):

      1. Skip Objective-C and go with Swift (unless the job specifically asks for Objective-C)
      2. Try http://www.raywenderlich.com (will help you to get up to speed faster, specially on topics that are interesting to you)
      3. Udacity offers 2 paid iOS Nanodegree programs but you can enroll on the courses for free, see https://www.udacity.com/courses/all
      Particularly these 4 free courses are project-based and will help you to build 4 apps that you can put on your resume,
      – Intro to iOS App Development with Swift
      – UIKit Fundamentals
      – iOS Networking with Swift
      – iOS Persistence and Core Data
      4. Finally to dive deep, and at your leisure, come back to Stanford U.

      Good luck!

  5. Mo #
    February 22, 2016

    How can I thank you!!?

    I found all the courses.
    What do you mean for Udacity is paid but I can go for free? I am confused

    btw in theory if I can do the iOS of Stanford, that would suffice itself right? What does it lack or not have?

    • February 23, 2016

      What do you mean for Udacity is paid but I can go for free? I am confused

      Udacity: the iOS course materials I posted above are all free. But if you want a certificate from Udacity (in the form of a Nanodegree), you do have to pay for it 🙂 Otherwise, the nanodgree program uses the same free courses. Additionally the paid program provides peer support, instructor help, code reviews, etc.

      btw in theory if I can do the iOS of Stanford, that would suffice itself right? What does it lack or not have?

      Stanford: CS193P is an awesome course and if you ace it, I believe it will get you started as an iOS developer without doubt. The only problem that I have seen is, it can be hard sometimes without enough Object Oriented programming experience. Also some of the assignments can be a little boring, whereas the Udacity assignments are usually a lot of fun.

      That being said, the journey is never over. There are so many aspects of iOS that I don’t think any single course/book can cover it all. I have compiled a list of resources here: http://objectcoder.com/2016/02/23/a-list-of-swift-and-ios-learning-resources-for-an-effective-learning-path/ in case you find it useful.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Basic HTML is allowed. Your email address will not be published.

Subscribe to this comment feed via RSS