34
Black Jack in Objective-C CS 355

Black Jack in Objective-C CS 355. Cards 52 cards in a standard poker deck –Each card has a suit heart spade diamond club –and a rank A, 2, 3, 4, 5, 6,

Embed Size (px)

Citation preview

Black Jack in Objective-C

CS 355

Cards

• 52 cards in a standard poker deck– Each card has a suit

• heart • spade • diamond • club

– and a rank• A, 2, 3, 4, 5, 6, 7, 8, 9, 10,

J, Q, K

Card Interface (Card.h)#import <Foundation/Foundation.h>

enum {HEART, SPADE, CLUB, DIAMOND};

enum {ACE=1, JACK=11, QUEEN=12, KING=13};

@interface Card : NSObject {

@private

int suit; // HEART, SPADE, DIAMOND, CLUB

int rank; // ACE, 2, 3, …, 10, JACK, QUEEN, KING

}

-(id)init;

-(id)initWithSuit:(int)s AndRank:(int)r;

-(int) suit;

-(int) rank;

@end

Card Implementation (Card.m)#import "Card.h"

@implementation Card

-(id)init {return [self initWithSuit:

SPADE AndRank: ACE];}

-(id)initWithSuit:(int)s AndRank:(int)r {

if ((self = [super init]) != nil) {

suit = s;

rank = r;

}

return self;

}

-(int)suit {return suit;}

-(int)rank {return rank;}

@end

-(id)initWithSuit:(int)s AndRank:(int)r {

if ((self = [super init]) != nil) {

suit = s;

rank = r;

}

return self;

}

Designated Initializer

• Most specialized (has most parameters)• Called by other initializers• Proper chaining of initializers:

– First call parent class’s designated initializer,– then initialize new instance variables

Accessors

• Note that instance variables are private.• A card’s suit and rank are retrieved via getter

methods – Usually have the same name as instance variable.

• Note that Card’s are immutable since we do not provide any setter methods.

-(int)suit {return suit;}

-(int)rank {return rank;}

Creating a new card

• We first send an alloc message to the Card class object which creates a new instance.

• Then we send an init message to this newly created instance.– It is important to capture the return value of the init method call, since it may return a different object then was created via alloc.

• The newly created card has a reference count of 1.

id card = [[Card alloc] init];

Black Jack Shoe

• In blackjack, a shoe is a device that can hold one to eight decks of cards from which the dealer can draw one card at time.

• When the shoe becomes sufficiently low, it is restocked and reshuffled.

Shoe.h#import <Foundation/Foundation.h>

@interface Shoe : NSObject {

@private

int numDecks;

id cards; // mutable array

}

-(id)initWithDeckCount:(int)n;

-(id)init;

-(void)dealloc;

-(void)shuffle;

-(id)deal;

-(int)cardsLeft;

-(void)reload;

@end

Shoe initialization(id)initWithDeckCount:(int)n {

if ((self = [super init]) != nil) {

numDecks = n;

cards = [[NSMutableArray alloc]

initWithCapacity: n*52];

[self reload];

}

return self;

}

Shoe destruction(void)dealloc {

[cards release];

[super dealloc];

}

• Release cards array.– Array releases each card

• Ends with call to superclass’s dealloc method.

Dealing cards from Shoe-(id)deal { if ([cards count] <= 0) return nil id card = [[cards lastObject] retain]; [cards removeLastObject]; return [card autorelease];}

• Note that we retain the last card before we release it!• We autorelease the card to safely perform the hand-off back to the caller!

Shuffling the Shoe

-(void)shuffle { const int n = [cards count]; for (int i = 0; i < n; i++) { int j = (int) (drand48()*n); if (i != j) [cards exchangeObjectAtIndex: i withObjectAtIndex: j]; }

}

Hand

• A hand is the set of cards held by a player.• A hand is valued by the sum of its cards:

– Aces worth 1 or 11– Face cards (Jack, Queen, King) are worth 10.

• A blackjack is a hand containing exactly two cards worth 21.

Hand.h#import <Foundation/Foundation.h>#import "card.h"

@interface Hand : NSObject {@private id cards;}-(id)init;-(void)dealloc;-(void)empty;-(void)insertCard:(Card *)card;-(unsigned)numCards;-(unsigned)softCount;-(unsigned)hardCount;-(unsigned)count;-(BOOL)busted;-(BOOL)blackjack;-(NSEnumerator *)cardEnumerator;@end

Hand init and dealloc-(id)init { self = [super init]; if (self != nil) { cards = [[NSMutableArray alloc] initWithCapacity: 10]; } return self;}

-(void)dealloc { [cards release]; [super dealloc];}

Inserting cards into and emptying a hand

-(void)insertCard:(Card *)card { [cards addObject: card];}

-(void)empty { [cards removeAllObjects];}

-(unsigned)numCards { return [cards count];}

Soft CountAces = 1

-(unsigned)softCount { NSEnumerator *e = [cards objectEnumerator]; id card; unsigned c = 0; while ((card = [e nextObject]) != nil) { int r = [card rank]; c += (r <= 10) ? r : 10; } return c;}

Hard CountAces = 11

-(unsigned)hardCount { NSEnumerator *e = [cards objectEnumerator]; id card; unsigned c = 0; while ((card = [e nextObject]) != nil) { int r = [card rank]; if (r == ACE) c += 11; else if (r <= 10) c += r; else // face card c += 10; } return c;}

Count closest to 21 without busting

-(unsigned)count { NSEnumerator *e = [cards objectEnumerator]; id card; unsigned c = 0; unsigned numAces = 0; while ((card = [e nextObject]) != nil) { int r = [card rank]; if (r == ACE) { c += 11; numAces++; } else c += (r <= 10) ? r : 10; } while (c > 21 && numAces > 0) { c -= 10; numAces--; } return c;}

Busted or Blackjack?-(BOOL)busted { return [self softCount] > 21;}

-(BOOL)blackjack { return [cards count] == 2 && [self hardCount] == 21;}

Player Hierarchy

NSObject

Player

DealerPlays by a fixed set of rules

HumanPlays using human I/O

CyborgPlays using AI

abstract base class

Player Base Classtypedef enum {HIT, STAY} Action;

@interface Player : NSObject {@protected int bank; id hand;}-(id)initWithBank:(int)amount;-(void)dealloc;-(int)betAmount;-(int)bank;-(void)bankCredit:(int)amount;-(void)bankDebit:(int)amount;-(Action)action;-(void)insertCard:(Card *)card;-(int)score;-(BOOL)busted;-(BOOL)blackjack;-(void)empty;-(NSEnumerator *) cardEnumerator;@end

Player init and dealloc

-(id)initWithBank:(int)amount { self = [super init]; if (self != nil) { bank = amount; hand = [[Hand alloc] init]; } return self;}

-(void)dealloc { [hand release]; [super dealloc];}

Default player strategy

-(int)betAmount {return bank;} // bet it all!

-(Action)action { // mimic dealer return ([hand hardCount] < 17) ? HIT : STAY;}

Other default behavior

-(int)bank {return bank;}-(void)bankCredit:(int)amount {bank += amount;}-(void)bankDebit:(int)amount {bank -= amount;}-(void)insertCard:(Card *)card { [hand insertCard: card];}-(int)score {return [hand count];}-(BOOL)busted {return [hand busted];}-(BOOL)blackjack {return [hand blackjack];}-(void)reset {[hand empty];}-(NSEnumerator *) cardEnumerator { return [hand cardEnumerator];}

The Dealer@interface Dealer : Player {@protected id shoe;}-(id)initWithDeckCount:(int)num;-(id)deal:(id)player;-(int)cardsLeft;-(void)reload;-(void)shuffle;@end

Dealer init and dealloc-(id)initWithDeckCount:(int)num { self = [super initWithBank: 0]; // has no bank if (self != nil) { shoe = [[Shoe alloc] initWithDeckCount: num]; } return self;}

-(void)dealloc { [shoe release]; [super dealloc];}

Dealer methods-(id)deal:(id)player { id card = [shoe draw]; if (player != nil) // player == nil => burn card [player insertCard: card]; return card;}

-(int)cardsLeft {return [shoe cardsLeft];}-(void)restock {[shoe restock];}-(void)shuffle {[shoe shuffle];}

// inherits action strategy (and other behavior) from Player

Table

• Dealer– Is a player– Has shoe

• 1 to 7 Players

Table.mDealer and 1 to 7 Players

@interface Table : NSObject {@private id dealer; id players; // mutable array}-(id)initWithDeckCount:(int)num;-(void)dealloc;-(int)numPlayers;-(void)addPlayer:(id)player;-(void)removePlayer:(id)player;-(id)dealer;-(NSEnumerator *)playerEnumerator;@end

Cyborg.hAn Example Player AI

@interface Cyborg : Player {// no new instance vars}-(int)betAmount;-(Action)action;@end

Cyborg method overrides

-(int)betAmount { int amount = (int) (50*drand48()); if (amount > bank) amount = bank; return amount;}

-(Action)action { return ([hand softCount] < 18) ? HIT : STAY;}

Human.hHuman Player

@interface Human : Player {// no new instance vars}-(int)betAmount; // get from user-(Action)action; // get from user@end