Model
//
// Card.h
// TonyGame
#import <Foundation/Foundation.h>
@interface Card : NSObject
@property (strong) NSString *contents;
@property (nonatomic) BOOL chosen;
@property (nonatomic) BOOL matched;
- (int)match:(NSArray *)otherCards;
- (BOOL)isMatched;
- (BOOL)isChosen;
@end
//
// Card.m
// TonyGame
//
#import "Card.h"
@interface Card()
@end
@implementation Card
@synthesize contents = _contents;
@synthesize chosen = _chosen;
@synthesize matched = _matched;
- (NSString *)contents
{
return _contents;
}
- (BOOL) chosen
{
return _chosen;
}
- (BOOL)isChosen
{
return _chosen;
}
- (void) setChosen:(BOOL)chosen
{
_chosen = chosen;
}
- (BOOL) matched
{
return _matched;
}
- (BOOL)isMatched
{
return _matched;
}
- (void) setMatched:(BOOL)matched
{
_matched = matched;
}
- (void) setContents:(NSString *)contents
{
_contents = contents;
}
- (int) match:(NSArray *)otherCards
{
int score = 0;
for(Card *card in otherCards){
if ([card.contents isEqualToString:self.contents]){
score = 1;
}
}
return score;
}
@end
// Deck.h
// TonyGame
#import <Foundation/Foundation.h>
#import "Card.h"
@interface Deck : NSObject
- (void) addCard:(Card *)card atTop:(BOOL)atTop;
- (void) addCard:(Card *)card;
- (Card *)drawRandomCard;
@end
// Deck.m
// TonyGame
#import "Deck.h"
@interface Deck()
@property (strong, nonatomic) NSMutableArray *cards;
@end
@implementation Deck
- (NSMutableArray *)cards
{
if (!_cards) _cards = [[NSMutableArray alloc] init];
return _cards;
}
- (void) addCard:(Card *)card atTop:(BOOL)atTop
{
if(atTop){
[self.cards insertObject:card atIndex:0];
}else{
[self.cards addObject:card];
}
}
- (void) addCard:(Card *)card
{
[self addCard:card atTop:NO];
}
- (Card *)drawRandomCard
{
Card *randomCard = nil;
if ([self.cards count]){
unsigned index = arc4random() % [self.cards count];
randomCard = self.cards[index];
[self.cards removeObjectAtIndex:index];
}
return randomCard;
}
@end
//
// PlayingCard.h
// TonyGame
#import "Card.h"
@interface PlayingCard : Card
@property (strong, nonatomic) NSString *suit;
@property (nonatomic) NSUInteger rank;
+ (NSArray *) validSuits;
+ (NSUInteger) maxRank;
@end
//
// PlayingCard.m
// TonyGame
//
#import "PlayingCard.h"
@implementation PlayingCard
- (int) match:(NSArray *)otherCards
{
int score = 0;
if ([otherCards count] == 1){
id card = [otherCards firstObject];
if ([card isKindOfClass:[PlayingCard class]]){
PlayingCard *othercard = [otherCards firstObject];
if ([self.suit isEqualToString:othercard.suit]) {
score = 1;
}else if (self.rank == othercard.rank){
score = 4;
}
}
}
return score;
}
- (NSString *)contents
{
//return [NSString stringWithFormat:@"%d%@", self.rank, self.suit];
NSArray *rankStrings = [PlayingCard rankStrings];
return [rankStrings[self.rank] stringByAppendingString:self.suit];
}
@synthesize suit = _suit;
+ (NSArray*) validSuits
{
return @[@"♣︎", @"♠️", @"♥️", @"♦️"];
}
- (void) setSuit:(NSString *)suit
{
if ([[PlayingCard validSuits] containsObject:suit]) {
_suit = suit;
}
}
- (NSString *)suit
{
return _suit ? _suit : @"?";
}
+ (NSArray *)rankStrings
{
return @[@"?", @"A",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10", @"J", @"Q", @"K"];
}
+ (NSUInteger)maxRank {return [[self rankStrings] count]-1;}
@end
//
// PlayingCardDeck.h
// TonyGame
#import "Deck.h"
@interface PlayingCardDeck : Deck
@end
//
// PlayingCardDeck.m
// TonyGame
//
#import "PlayingCardDeck.h"
#import "PlayingCard.h"
@implementation PlayingCardDeck
- (instancetype)init
{
self = [super init];
if(self){
for (NSString *suit in [PlayingCard validSuits]) {
for (NSUInteger rank = 1; rank <= [PlayingCard maxRank]; rank++) {
PlayingCard *card = [[PlayingCard alloc] init];
card.rank = rank;
card.suit = suit;
[self addCard:card];
}
}
}
return self;
}
@end
//
// CardMatchingGame.h
// TonyGame
//
#import <Foundation/Foundation.h>
#import "Deck.h"
#import "Card.h"
@interface CardMatchingGame : NSObject
- (instancetype)initWithCardCount:(NSUInteger)count usingDeck:(Deck *) deck;
- (void)chooseCardAtIndex:(NSUInteger)index;
- (Card *)cardAtIndex:(NSUInteger)index;
@property (nonatomic, readonly) NSInteger score;
@end
//
// CardMatchingGame.m
// TonyGame
#import "CardMatchingGame.h"
#import "Card.h"
@interface CardMatchingGame()
@property (nonatomic, readwrite) NSInteger score;
@property (nonatomic, strong) NSMutableArray *cards; //
@end
@implementation CardMatchingGame
- (NSMutableArray *)cards
{
if (!_cards) _cards = [[NSMutableArray alloc] init];
return _cards;
}
- (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;
}
static const int MISMATCH_PENALTY = 2;
static const int MATCH_BONUS = 4;
static const int COST_TO_CHOOSE = 1;
- (void)chooseCardAtIndex:(NSUInteger)index
{
Card *card = [self cardAtIndex:index];
if (!card.isMatched) {
if (card.isChosen){
card.chosen = NO;
}else{
//match against another card
for (Card *othercard in self.cards){
if (othercard.isChosen && !othercard.isMatched){
int matchScore = [card match:@[othercard]];
if (matchScore){
self.score += matchScore * MATCH_BONUS;
card.matched = YES;
othercard.matched = YES;
}else{
self.score -= MISMATCH_PENALTY;
othercard.chosen = NO;
}
break;
}
}
self.score -= COST_TO_CHOOSE;
card.chosen = YES;
}
}
}
- (Card *)cardAtIndex:(NSUInteger)index
{
return (index < [self.cards count]) ? self.cards[index] : nil;
}
- (instancetype)init
{
return nil;
}
@end