0

Been stuck on this problem for three days. Thought writing this question out would take longer than solving the problem myself, but I'm getting nowhere with this. I'll try to lay this out as concisely and logically as I can. In Objective-C, Cocos2D-iPhone 2.0, Xcode 4.6.

I'm writing a texas hold'em game and I'm stuck on trying to get my gameplay layer to evaluate which hands are straight flushes and royal flushes.

(For those unfamiliar with Texas Hold'em or poker in general, once all possible cards have been dealt out, the player has to make his best 5-card hand out of 7 total cards. In this instance, I'm only concerned with figuring out whether the player has a straight flush, which is any 5 cards of the same suit that are also in sequential order. [e.g. 7, 8, 9, 10, and Jack of clubs, or the ace, deuce, 3, 4, and 5 of hearts, etc. A "royal" flush is simply the highest straight flush, which is Ten, Jack, Queen, King, and Ace all of the same suit.])

All I have for the Card class are methods for allocation and movement. I feel comfortable saying that those are working fine. I haven't had any problems there.

Here are the pertinent parts of my Card class:

Card.h

#import <Foundation/Foundation.h>
#import "cocos2d.h"

@interface Card : CCSprite {
    BOOL removedFromLayer, reachedDestination, isMoving;
    NSString *imageName;
    NSString *suit;
    NSNumber *rank;
}

@property BOOL removedFromLayer, reachedDestination, isMoving;
@property (nonatomic, retain) NSNumber *rank;
@property (nonatomic, retain) NSString *suit;
@property (nonatomic, retain) NSString *imageName;

// ... movement and animation methods

@end

Implementation:

#import "Card.h"
@implementation Card
@synthesize removedFromLayer, reachedDestination, isMoving, rank, suit, imageName;
    // ... implementations
@end

I extended the NSMutableArray class to include poker hand evaluation logic. I tried initially to create a subclass of NSMutableArray, but as an experience programmer would recognize, it didn't work out too well. The sorting methods are working fine, as far as I can tell from the console readouts. I'll just stick with the straight flush method for now. I admit it's pretty ugly. (Ha. "Pretty ugly."):

#import "NSMutableArray+HandAnalysis.h"
#import "Card.h"

#define cards1And2AreSequential (card1Rank == (card2Rank - 1))
#define cards2And3AreSequential (card2Rank == (card3Rank - 1))
#define cards3And4AreSequential (card3Rank == (card4Rank - 1))
#define cards4And5AreSequential (card4Rank == (card5Rank - 1))
#define cards5And6AreSequential (card5Rank == (card6Rank - 1))
#define cards6And7AreSequential (card6Rank == (card7Rank - 1))

#define cards1And2AreSameSuit (card1Suit == card2Suit)
#define cards2And3AreSameSuit (card2Suit == card3Suit)
#define cards3And4AreSameSuit (card3Suit == card4Suit)
#define cards4And5AreSameSuit (card4Suit == card5Suit)
#define cards5And6AreSameSuit (card5Suit == card6Suit)
#define cards6And7AreSameSuit (card6Suit == card7Suit)

#define firstCardIsAnAce [[firstCard valueForKey:@"rank"] intValue] == 1
#define lastCardIsAKing [[lastCard valueForKey:@"rank"] intValue] == 13
#define secondToLastCardIsAQueen [[secondToLastCard valueForKey:@"rank"] intValue] == 12
#define thirdToLastCardIsAJack [[thirdToLastCard valueForKey:@"rank"] intValue] == 11
#define fourthToLastCardIsATen [[fourthToLastCard valueForKey:@"rank"] intValue] == 10

// clubs (NOTE:  These do not terminate with a semi-colon)
#define firstCardIsAClub [[firstCard valueForKey:@"suit"] isEqualToString:@"club"]
#define lastCardIsAClub [[lastCard valueForKey:@"suit"] isEqualToString:@"club"]
#define secondToLastCardIsAClub [[secondToLastCard valueForKey:@"suit"] isEqualToString:@"club"]
#define thirdToLastCardIsAClub [[thirdToLastCard valueForKey:@"suit"] isEqualToString:@"club"]
#define fourthToLastCardIsAClub [[fourthToLastCard valueForKey:@"suit"] isEqualToString:@"club"]

// diamonds
#define firstCardIsADiamond [[firstCard valueForKey:@"suit"] isEqualToString:@"diamond"]
#define lastCardIsADiamond [[lastCard valueForKey:@"suit"] isEqualToString:@"diamond"]
#define secondToLastCardIsADiamond [[secondToLastCard valueForKey:@"suit"] isEqualToString:@"diamond"]
#define thirdToLastCardIsADiamond [[thirdToLastCard valueForKey:@"suit"] isEqualToString:@"diamond"]
#define fourthToLastCardIsADiamond [[fourthToLastCard valueForKey:@"suit"] isEqualToString:@"diamond"]

// hearts
#define firstCardIsAHeart [[firstCard valueForKey:@"suit"] isEqualToString:@"heart"]
#define lastCardIsAHeart [[lastCard valueForKey:@"suit"] isEqualToString:@"heart"]
#define secondToLastCardIsAHeart [[secondToLastCard valueForKey:@"suit"] isEqualToString:@"heart"]
#define thirdToLastCardIsAHeart [[thirdToLastCard valueForKey:@"suit"] isEqualToString:@"heart"]
#define fourthToLastCardIsAHeart [[fourthToLastCard valueForKey:@"suit"] isEqualToString:@"heart"]

// spades
#define firstCardIsASpade [[firstCard valueForKey:@"suit"] isEqualToString:@"spade"]
#define lastCardIsASpade [[lastCard valueForKey:@"suit"] isEqualToString:@"spade"]
#define secondToLastCardIsASpade [[secondToLastCard valueForKey:@"suit"] isEqualToString:@"spade"]
#define thirdToLastCardIsASpade [[thirdToLastCard valueForKey:@"suit"] isEqualToString:@"spade"]
#define fourthToLastCardIsASpade [[fourthToLastCard valueForKey:@"suit"] isEqualToString:@"spade"]


@implementation NSMutableArray (HandAnalysis)

-(NSMutableArray *)sortByRank {

    NSSortDescriptor *rankSD = [[NSSortDescriptor alloc] initWithKey:@"rank" ascending:YES];

    NSArray *sortDescriptors = [NSArray arrayWithObject:rankSD];
    NSArray *sortedHand = [self sortedArrayUsingDescriptors:sortDescriptors];
    NSMutableArray *handOrganizedByRank = [NSMutableArray arrayWithArray:sortedHand];

    for (Card* card in handOrganizedByRank) {
        NSLog(@"%@", [card valueForKey:@"rank"]);
    }

    return handOrganizedByRank;
}

-(NSMutableArray *)sortBySuit {

    NSSortDescriptor *suitSD = [[NSSortDescriptor alloc] initWithKey:@"suit" ascending:YES];

    NSArray *sortDescriptors = [NSArray arrayWithObject:suitSD];
    NSArray *sortedHand = [self sortedArrayUsingDescriptors:sortDescriptors];
    NSMutableArray *handOrganizedBySuit = [NSMutableArray arrayWithArray:sortedHand];

    for (Card* card in handOrganizedBySuit) {
        NSLog(@"%@", [card valueForKey:@"suit"]);
    }

    return handOrganizedBySuit;
}

-(BOOL)isStraightFlush {

    [self sortByRank];
    [self sortBySuit];

    NSLog(@"Amount of cards in the array:  %d", [self count]);

    // this section is for if there are 7 cards in the array total.
    if ([self count] == 7) {

        int card1Rank = [[[self objectAtIndex:0] valueForKey:@"rank"] intValue];
        int card2Rank = [[[self objectAtIndex:1] valueForKey:@"rank"] intValue];
        int card3Rank = [[[self objectAtIndex:2] valueForKey:@"rank"] intValue];
        int card4Rank = [[[self objectAtIndex:3] valueForKey:@"rank"] intValue];
        int card5Rank = [[[self objectAtIndex:4] valueForKey:@"rank"] intValue];
        int card6Rank = [[[self objectAtIndex:5] valueForKey:@"rank"] intValue];
        int card7Rank = [[[self objectAtIndex:6] valueForKey:@"rank"] intValue];

        id card1Suit = [[self objectAtIndex:0] valueForKey:@"suit"];
        id card2Suit = [[self objectAtIndex:1] valueForKey:@"suit"];
        id card3Suit = [[self objectAtIndex:2] valueForKey:@"suit"];
        id card4Suit = [[self objectAtIndex:3] valueForKey:@"suit"];
        id card5Suit = [[self objectAtIndex:4] valueForKey:@"suit"];
        id card6Suit = [[self objectAtIndex:5] valueForKey:@"suit"];
        id card7Suit = [[self objectAtIndex:6] valueForKey:@"suit"];

        // if all cards (1-7) are straight flush
        if ((cards1And2AreSequential && cards2And3AreSequential && cards3And4AreSequential && cards4And5AreSequential && cards5And6AreSequential && cards6And7AreSequential && cards1And2AreSameSuit && cards2And3AreSameSuit && cards3And4AreSameSuit && cards4And5AreSameSuit && cards5And6AreSameSuit && cards6And7AreSameSuit)) {
            NSLog(@"Player has a seven-card straight flush.  %d items in the array.", [self count]);

            return TRUE;
        }

        // (6-card straight flushes)  if cards 1-6 or 2-7 are straight flush
        else if ((cards1And2AreSequential && cards2And3AreSequential && cards3And4AreSequential && cards4And5AreSequential && cards5And6AreSequential && cards1And2AreSameSuit && cards2And3AreSameSuit && cards3And4AreSameSuit && cards4And5AreSameSuit && cards5And6AreSameSuit) ||  (cards2And3AreSequential && cards3And4AreSequential && cards4And5AreSequential && cards5And6AreSequential && cards6And7AreSequential && cards2And3AreSameSuit && cards3And4AreSameSuit && cards4And5AreSameSuit && cards5And6AreSameSuit && cards6And7AreSameSuit)) {
            NSLog(@"Player has a six-card straight flush.  %d in the array.", [self count]);

            return TRUE;
        }

        // (5-card straight flushes)  if 1-5 or 2-6 or 3-7 are straight flush
        else if ((cards1And2AreSequential && cards2And3AreSequential && cards3And4AreSequential && cards4And5AreSequential && cards1And2AreSameSuit && cards2And3AreSameSuit && cards3And4AreSameSuit && cards4And5AreSameSuit) ||  (cards2And3AreSequential && cards3And4AreSequential && cards4And5AreSequential && cards5And6AreSequential && cards2And3AreSameSuit && cards3And4AreSameSuit && cards4And5AreSameSuit && cards5And6AreSameSuit) || (cards3And4AreSequential && cards4And5AreSequential && cards5And6AreSequential && cards6And7AreSequential && cards3And4AreSameSuit && cards4And5AreSameSuit && cards5And6AreSameSuit && cards6And7AreSameSuit)) {

            NSLog(@"Player has a straight flush.  %d in the array.", [self count]);

            return TRUE;
        } else {
        NSLog(@"Player does not have a straight flush.  %d in the array.", [self count]);
        return  FALSE;
        }
    }

    // this section is for if there are 6 cards in the array total.
    else if ([self count] == 6) {
        int card1Rank = [[[self objectAtIndex:0] valueForKey:@"rank"] intValue];
        int card2Rank = [[[self objectAtIndex:1] valueForKey:@"rank"] intValue];
        int card3Rank = [[[self objectAtIndex:2] valueForKey:@"rank"] intValue];
        int card4Rank = [[[self objectAtIndex:3] valueForKey:@"rank"] intValue];
        int card5Rank = [[[self objectAtIndex:4] valueForKey:@"rank"] intValue];
        int card6Rank = [[[self objectAtIndex:5] valueForKey:@"rank"] intValue];

        id card1Suit = [[self objectAtIndex:0] valueForKey:@"suit"];
        id card2Suit = [[self objectAtIndex:1] valueForKey:@"suit"];
        id card3Suit = [[self objectAtIndex:2] valueForKey:@"suit"];
        id card4Suit = [[self objectAtIndex:3] valueForKey:@"suit"];
        id card5Suit = [[self objectAtIndex:4] valueForKey:@"suit"];
        id card6Suit = [[self objectAtIndex:5] valueForKey:@"suit"];

            // added
            // (6-card straight flush)  if cards 1-6 is straight flush
            if ((cards1And2AreSequential && cards2And3AreSequential && cards3And4AreSequential && cards4And5AreSequential && cards5And6AreSequential && cards1And2AreSameSuit && cards2And3AreSameSuit && cards3And4AreSameSuit && cards4And5AreSameSuit && cards5And6AreSameSuit)) {
                NSLog(@"Player has a six-card straight flush.  %d in the array.", [self count]);

                return TRUE;
            }
            // (5-card straight flushes)  if cards 1-5 or cards 2-6 make a straight flush
            else if ((cards1And2AreSequential && cards2And3AreSequential && cards3And4AreSequential && cards4And5AreSequential && cards1And2AreSameSuit && cards2And3AreSameSuit && cards3And4AreSameSuit && cards4And5AreSameSuit) ||  (cards2And3AreSequential && cards3And4AreSequential && cards4And5AreSequential && cards5And6AreSequential && cards2And3AreSameSuit && cards3And4AreSameSuit && cards4And5AreSameSuit && cards5And6AreSameSuit)) {
                NSLog(@"Player has a straight flush.  %d in the array.", [self count]);

                return TRUE;
            } else {
            NSLog(@"Player does not have a straight flush.  %d in the array.", [self count]);
            return  FALSE;
            }
        }

    // if only 5 cards in the array, only one possible straight flush
    else if ([self count] == 5) {
        int card1Rank = [[[self objectAtIndex:0] valueForKey:@"rank"] intValue];
        int card2Rank = [[[self objectAtIndex:1] valueForKey:@"rank"] intValue];
        int card3Rank = [[[self objectAtIndex:2] valueForKey:@"rank"] intValue];
        int card4Rank = [[[self objectAtIndex:3] valueForKey:@"rank"] intValue];
        int card5Rank = [[[self objectAtIndex:4] valueForKey:@"rank"] intValue];

        id card1Suit = [[self objectAtIndex:0] valueForKey:@"suit"];
        id card2Suit = [[self objectAtIndex:1] valueForKey:@"suit"];
        id card3Suit = [[self objectAtIndex:2] valueForKey:@"suit"];
        id card4Suit = [[self objectAtIndex:3] valueForKey:@"suit"];
        id card5Suit = [[self objectAtIndex:4] valueForKey:@"suit"];

        if (cards1And2AreSequential && cards2And3AreSequential && cards3And4AreSequential && cards4And5AreSequential && cards1And2AreSameSuit && cards2And3AreSameSuit && cards3And4AreSameSuit && cards4And5AreSameSuit) {
            NSLog(@"Player has a straight flush.  %d in the array.", [self count]);

            return TRUE;
        } else {
            NSLog(@"Player does not have a straight flush.  %d in the array.", [self count]);
            return FALSE;
        }
    }
    NSLog(@"Something is wrong in the isStraightFlush method.");

    return 0;
}

@end

And the following is from my CCGamePlayLayer. This layer handles creating, shuffling, and dealing the decks--in this case a loaded deck that will give me a royal flush every time. We first make the deck, which consists of two off-suit deuces and the 10, J, Q, K, and A of clubs. Then we call the shuffle method, then we deal out the board, which includes the player's 2 hole cards, 3 cards on the flop, 1 on the turn, and 1 on the river. We then call the evaluateHand method to determine the best hand the player can make with his 7 cards. Once it's determined what kind of hand the player has, the evaluateHand method just shows a UIAlertView that tells the player what the hand is.

CCGamePlayLayer.h

#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import <GameKit/GameKit.h>
#import <UIKit/UIKit.h>
#import "NSMutableArray+HandAnalysis.h"

@interface CCGamePlayLayer : CCLayer <CCTargetedTouchDelegate> {

    NSMutableArray *deck;
}

@property (nonatomic, retain) NSMutableArray *deck;
    @property (nonatomic, retain) hasPair, hasTwoPair, hasSet, hasStraight, hasFlush, hasBoat, hasQuads, hasStraightFlush, hasRoyalFlush;

CCGamePlayLayer.m

#import "CCGamePlayLayer.h"
#import "ItemsViewController.h"
#import "MGAppDelegate.h"
#import "Card.h"

@implementation CCGamePlayLayer

@synthesize deck;
@synthesize hasPair, hasTwoPair, hasSet, hasStraight, hasFlush, hasBoat, hasQuads, hasStraightFlush, hasRoyalFlush;

-(id)init {
    if (self = [super init]) {

        //  ... Make the buttons and background

        [self makeLoadedRoyalFlushDeck];
        [self shuffle];

        NSLog(@"Here's the shuffled deck, from the init method:");

        for (Card *c in deck) {
            NSLog(@"%@", c.imageName);
        }

        [self dealLoadedHoleCards];
    }
    return self;
}

-(NSMutableArray *)makeLoadedRoyalFlushDeck {
    Card *aceC = [Card spriteWithFile:@"pbwb1c.png"];
    [aceC setValue:@"Ac" forKey:@"imageName"];
    [aceC setValue:[NSNumber numberWithInt:1] forKey:@"rank"];
    [aceC setValue:@"club" forKey:@"suit"];

    Card *tenC = [Card spriteWithFile:@"pbwbtc.png"];
    [tenC setValue:@"Tc" forKey:@"imageName"];
    [tenC setValue:[NSNumber numberWithInt:10] forKey:@"rank"];
    [tenC setValue:@"club" forKey:@"suit"];

    Card *jackC = [Card spriteWithFile:@"pbwbjc.png"];
    [jackC setValue:@"Jc" forKey:@"imageName"];
    [jackC setValue:[NSNumber numberWithInt:11] forKey:@"rank"];
    [jackC setValue:@"club" forKey:@"suit"];

    Card *queenC = [Card spriteWithFile:@"pbwbqc.png"];
    [queenC setValue:@"Qc" forKey:@"imageName"];
    [queenC setValue:[NSNumber numberWithInt:12] forKey:@"rank"];
    [queenC setValue:@"club" forKey:@"suit"];

    Card *kingC = [Card spriteWithFile:@"pbwbkc.png"];
    [kingC setValue:@"Kc" forKey:@"imageName"];
    [kingC setValue:[NSNumber numberWithInt:13] forKey:@"rank"];
    [kingC setValue:@"club" forKey:@"suit"];

    Card *deuceS = [Card spriteWithFile:@"pbwb2s.png"];
    [deuceS setValue:@"2s" forKey:@"imageName"];
    [deuceS setValue:[NSNumber numberWithInt:2] forKey:@"rank"];
    [deuceS setValue:@"spade" forKey:@"suit"];

    Card *deuceD = [Card spriteWithFile:@"pbwb2d.png"];
    [deuceD setValue:@"2d" forKey:@"imageName"];
    [deuceD setValue:[NSNumber numberWithInt:2] forKey:@"rank"];
    [deuceD setValue:@"diamond" forKey:@"suit"];

    deck = [NSMutableArray arrayWithObjects: deuceS, deuceD, aceC, tenC, jackC, queenC, kingC, nil];

    for (Card *c in deck) {
        NSLog(@"%@", c.imageName);
    }

    return deck;
}

-(void)shuffle {
    NSLog(@"[self.deck count] == %d", [self.deck count]);
    for (int i = [self.deck count] - 1; i > 0; i--) {
        [self.deck exchangeObjectAtIndex:(arc4random_uniform([self.deck count] - 1)) withObjectAtIndex:i];
    }
    NSLog(@"The deck has been shuffled.");
    NSLog(@"Here is the shuffled deck:");

    for (Card *c in deck) {
        NSLog(@"%@", c.imageName);
    }
}

-(void)evaluateHand {
    if (playerHoleCard1 && playerHoleCard2 && !flop1 && !flop2 && !flop3 && !turn && !river) {
        UIAlertView *holeCardsAlert = [[UIAlertView alloc] initWithTitle:@"Whoa!" message:@"You've only been dealt your hole cards!  Slow down, there, killer!" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [holeCardsAlert show];
    }
    else if (playerHoleCard1 && playerHoleCard2 && flop1 && flop2 && flop3 && !turn && !river) {
        UIAlertView *flopAlert = [[UIAlertView alloc] initWithTitle:@"FLOP" message:@"You need to wait until the board is completely dealt out to evaluate your hand." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [flopAlert show];
    }
    else if (playerHoleCard1 && playerHoleCard2 && flop1 && flop2 && flop3 && turn && !river) {
        UIAlertView *turnAlert = [[UIAlertView alloc] initWithTitle:@"TURN" message:@"Almost there.  One card to go, and then I'll tell you what kind of hand you have." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [turnAlert show];
    }
    else if (playerHoleCard1 && playerHoleCard2 && flop1 && flop2 && flop3 && turn && river) {

        // put the player's 2 hole cards and the 5 board cards in an array for sorting
        NSMutableArray *allCards = [NSMutableArray arrayWithObjects:flop1, flop2, flop3, turn, river, playerHoleCard1, playerHoleCard2, nil];

        // first check for higher hands
        // royal flush
        id sequentialHand           = [allCards sortByRank];
        id sequentialAndSuitedHand  = [sequentialHand sortBySuit];

        // Check for straight flush first
        hasRoyalFlush = [sequentialAndSuitedHand isStraightFlush];

        // Checking for straight or flush
        hasStraight = [sequentialHand isStraight];
        hasFlush = [sequentialAndSuitedHand isFlush];

        // Checking for quads, we check the original array
        hasQuads = [allCards isQuads];

        // Check for SF
        if (hasStraight == TRUE && hasFlush == TRUE) {
            if (hasRoyalFlush == TRUE) {
                hasStraightFlush = FALSE;
                hasStraight = FALSE;
                hasFlush = FALSE;
                NSLog(@"hasRoyalFlush == TRUE");
            } else if (hasRoyalFlush == FALSE) {
                NSLog(@"hasRoyalFlush == FALSE");
            }
        }
        else if (hasRoyalFlush == FALSE) {
                hasStraight = FALSE;
                hasFlush = FALSE;
                UIAlertView *straightFlushAlert = [[UIAlertView alloc] initWithTitle:@"STRAIGHT FLUSH" message:@"You have a straight flush." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
                [straightFlushAlert show];
            } else if (hasStraightFlush == FALSE) {
                NSLog(@"hasStraightFlush == FALSE");
            } else {
                NSLog(@"Some problem in determining whether hasStraightFlush is TRUE or FALSE.");
            }

        // check for straight
        if (hasStraight == TRUE) {
            UIAlertView *straightAlert = [[UIAlertView alloc] initWithTitle:@"STRAIGHT" message:@"You have a straight." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [straightAlert show];

            NSLog(@"Player has a straight.");
        }

        if (hasFlush == TRUE) {
            UIAlertView *flushAlert = [[UIAlertView alloc] initWithTitle:@"FLUSH" message:@"You have a flush." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [flushAlert show];

            NSLog(@"Player has a flush.");
        }

        if (hasQuads == TRUE) {
            hasPair = FALSE;
            hasTwoPair = FALSE;
            hasStraight = FALSE;
            hasFlush = FALSE;
            UIAlertView *quadsAlert = [[UIAlertView alloc] initWithTitle:@"QUADS" message:@"You have four of a kind." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [quadsAlert show];
        }
    }
}

@end

And here's what I get from the console when I run this and try to evaluate the hand I have:

2013-03-14 10:27:53.045 TexasHoldemGame[7600:c07] sortByRank called.
2013-03-14 10:27:53.045 TexasHoldemGame[7600:c07] 1
2013-03-14 10:27:53.046 TexasHoldemGame[7600:c07] 2
2013-03-14 10:27:53.047 TexasHoldemGame[7600:c07] 2
2013-03-14 10:27:53.048 TexasHoldemGame[7600:c07] 10
2013-03-14 10:27:53.049 TexasHoldemGame[7600:c07] 11
2013-03-14 10:27:53.049 TexasHoldemGame[7600:c07] 12
2013-03-14 10:27:53.050 TexasHoldemGame[7600:c07] 13
2013-03-14 10:27:53.050 TexasHoldemGame[7600:c07] For thoroughness, here it is with both values and suits:
2013-03-14 10:27:53.051 TexasHoldemGame[7600:c07] 1 of club
2013-03-14 10:27:53.051 TexasHoldemGame[7600:c07] 2 of diamond
2013-03-14 10:27:53.052 TexasHoldemGame[7600:c07] 2 of spade
2013-03-14 10:27:53.053 TexasHoldemGame[7600:c07] 10 of club
2013-03-14 10:27:53.053 TexasHoldemGame[7600:c07] 11 of club
2013-03-14 10:27:53.054 TexasHoldemGame[7600:c07] 12 of club
2013-03-14 10:27:53.054 TexasHoldemGame[7600:c07] 13 of club
2013-03-14 10:27:53.055 TexasHoldemGame[7600:c07] sortBySuit called.
2013-03-14 10:27:53.055 TexasHoldemGame[7600:c07] club
2013-03-14 10:27:53.056 TexasHoldemGame[7600:c07] club
2013-03-14 10:27:53.056 TexasHoldemGame[7600:c07] club
2013-03-14 10:27:53.057 TexasHoldemGame[7600:c07] club
2013-03-14 10:27:53.057 TexasHoldemGame[7600:c07] club
2013-03-14 10:27:53.058 TexasHoldemGame[7600:c07] diamond
2013-03-14 10:27:53.058 TexasHoldemGame[7600:c07] spade
2013-03-14 10:27:53.059 TexasHoldemGame[7600:c07] For thoroughness, here it is with both values and suits:
2013-03-14 10:27:53.059 TexasHoldemGame[7600:c07] 1 of club
2013-03-14 10:27:53.060 TexasHoldemGame[7600:c07] 10 of club
2013-03-14 10:27:53.061 TexasHoldemGame[7600:c07] 11 of club
2013-03-14 10:27:53.061 TexasHoldemGame[7600:c07] 12 of club
2013-03-14 10:27:53.062 TexasHoldemGame[7600:c07] 13 of club
2013-03-14 10:27:53.062 TexasHoldemGame[7600:c07] 2 of diamond
2013-03-14 10:27:53.063 TexasHoldemGame[7600:c07] 2 of spade
2013-03-14 10:27:53.063 TexasHoldemGame[7600:c07] isStraightFlush bool method called.
2013-03-14 10:27:53.064 TexasHoldemGame[7600:c07] sortByRank called.
2013-03-14 10:27:53.064 TexasHoldemGame[7600:c07] 1
2013-03-14 10:27:53.065 TexasHoldemGame[7600:c07] 2
2013-03-14 10:27:53.066 TexasHoldemGame[7600:c07] 2
2013-03-14 10:27:53.067 TexasHoldemGame[7600:c07] 10
2013-03-14 10:27:53.067 TexasHoldemGame[7600:c07] 11
2013-03-14 10:27:53.069 TexasHoldemGame[7600:c07] 12
2013-03-14 10:27:53.070 TexasHoldemGame[7600:c07] 13
2013-03-14 10:27:53.070 TexasHoldemGame[7600:c07] For thoroughness, here it is with both values and suits:
2013-03-14 10:27:53.071 TexasHoldemGame[7600:c07] 1 of club
2013-03-14 10:27:53.072 TexasHoldemGame[7600:c07] 2 of diamond
2013-03-14 10:27:53.073 TexasHoldemGame[7600:c07] 2 of spade
2013-03-14 10:27:53.073 TexasHoldemGame[7600:c07] 10 of club
2013-03-14 10:27:53.073 TexasHoldemGame[7600:c07] 11 of club
2013-03-14 10:27:53.074 TexasHoldemGame[7600:c07] 12 of club
2013-03-14 10:27:53.074 TexasHoldemGame[7600:c07] 13 of club
2013-03-14 10:27:53.076 TexasHoldemGame[7600:c07] sortBySuit called.
2013-03-14 10:27:53.077 TexasHoldemGame[7600:c07] club
2013-03-14 10:27:53.078 TexasHoldemGame[7600:c07] club
2013-03-14 10:27:53.079 TexasHoldemGame[7600:c07] club
2013-03-14 10:27:53.080 TexasHoldemGame[7600:c07] club
2013-03-14 10:27:53.082 TexasHoldemGame[7600:c07] club
2013-03-14 10:27:53.082 TexasHoldemGame[7600:c07] diamond
2013-03-14 10:27:53.083 TexasHoldemGame[7600:c07] spade
2013-03-14 10:27:53.083 TexasHoldemGame[7600:c07] For thoroughness, here it is with both values and suits:
2013-03-14 10:27:53.084 TexasHoldemGame[7600:c07] 1 of club
2013-03-14 10:27:53.084 TexasHoldemGame[7600:c07] 10 of club
2013-03-14 10:27:53.085 TexasHoldemGame[7600:c07] 11 of club
2013-03-14 10:27:53.086 TexasHoldemGame[7600:c07] 12 of club
2013-03-14 10:27:53.087 TexasHoldemGame[7600:c07] 13 of club
2013-03-14 10:27:53.088 TexasHoldemGame[7600:c07] 2 of diamond
2013-03-14 10:27:53.089 TexasHoldemGame[7600:c07] 2 of spade
2013-03-14 10:27:53.090 TexasHoldemGame[7600:c07] Amount of cards in the array:  7
2013-03-14 10:27:53.092 TexasHoldemGame[7600:c07] Player does not have a straight flush.  7 in the array.
2013-03-14 10:27:53.092 TexasHoldemGame[7600:c07] isStraight called.
2013-03-14 10:27:53.093 TexasHoldemGame[7600:c07] Back in the isStraight method again.
2013-03-14 10:27:53.094 TexasHoldemGame[7600:c07] We're about to start iterating through the array, and here are the ranks in the array, before elimination:
2013-03-14 10:27:53.095 TexasHoldemGame[7600:c07] Rank:  1
2013-03-14 10:27:53.096 TexasHoldemGame[7600:c07] Rank:  2
2013-03-14 10:27:53.098 TexasHoldemGame[7600:c07] Rank:  2
2013-03-14 10:27:53.098 TexasHoldemGame[7600:c07] Rank:  10
2013-03-14 10:27:53.099 TexasHoldemGame[7600:c07] Rank:  11
2013-03-14 10:27:53.099 TexasHoldemGame[7600:c07] Rank:  12
2013-03-14 10:27:53.099 TexasHoldemGame[7600:c07] Rank:  13
2013-03-14 10:27:53.102 TexasHoldemGame[7600:c07] This is how many items are in the array, currently:  6
2013-03-14 10:27:53.103 TexasHoldemGame[7600:c07] After elimination:
2013-03-14 10:27:53.104 TexasHoldemGame[7600:c07] Rank:  1
2013-03-14 10:27:53.104 TexasHoldemGame[7600:c07] Rank:  2
2013-03-14 10:27:53.105 TexasHoldemGame[7600:c07] Rank:  10
2013-03-14 10:27:53.105 TexasHoldemGame[7600:c07] Rank:  11
2013-03-14 10:27:53.105 TexasHoldemGame[7600:c07] Rank:  12
2013-03-14 10:27:53.106 TexasHoldemGame[7600:c07] Rank:  13
2013-03-14 10:27:53.106 TexasHoldemGame[7600:c07] There are 5 or more cards.  Proceed.
2013-03-14 10:27:53.107 TexasHoldemGame[7600:c07] tempHand objectAtIndex:0 == 1
2013-03-14 10:27:53.107 TexasHoldemGame[7600:c07] tempHand objectAtIndex:1 == 2
2013-03-14 10:27:53.108 TexasHoldemGame[7600:c07] tempHand objectAtIndex:2 == 10
2013-03-14 10:27:53.143 TexasHoldemGame[7600:c07] tempHand objectAtIndex:3 == 11
2013-03-14 10:27:53.144 TexasHoldemGame[7600:c07] tempHand objectAtIndex:4 == 12
2013-03-14 10:27:53.144 TexasHoldemGame[7600:c07] tempHand objectAtIndex:5 == 13
2013-03-14 10:27:53.145 TexasHoldemGame[7600:c07] You have a straight.
2013-03-14 10:27:53.145 TexasHoldemGame[7600:c07] isFlush bool method called.
2013-03-14 10:27:53.146 TexasHoldemGame[7600:c07] FLUSH!!!  FLUSH!!!  FLUSH!!!
2013-03-14 10:27:53.146 TexasHoldemGame[7600:c07] isQuads bool method called.
2013-03-14 10:27:53.147 TexasHoldemGame[7600:c07] Print out the array, so we know what we're dealing with:
2013-03-14 10:27:53.148 TexasHoldemGame[7600:c07] 12 of club
2013-03-14 10:27:53.148 TexasHoldemGame[7600:c07] 1 of club
2013-03-14 10:27:53.149 TexasHoldemGame[7600:c07] 13 of club
2013-03-14 10:27:53.150 TexasHoldemGame[7600:c07] 2 of diamond
2013-03-14 10:27:53.150 TexasHoldemGame[7600:c07] 2 of spade
2013-03-14 10:27:53.151 TexasHoldemGame[7600:c07] 11 of club
2013-03-14 10:27:53.152 TexasHoldemGame[7600:c07] 10 of club
2013-03-14 10:27:53.152 TexasHoldemGame[7600:c07] Number of Aces:  1
Number of Deuces:  2
Number of Threes:  0
Number of Fours:  0
Number of Fives:  0
Number of Sixes:  0
Number of Sevens:  0
Number of Eights:  0
Number of Nines:  0
Number of Tens:  1
Number of Jacks:  1
Number of Queens:  1
Number of Kings:  1
2013-03-14 10:27:53.153 TexasHoldemGame[7600:c07] PLayer does not have quads.
2013-03-14 10:27:53.153 TexasHoldemGame[7600:c07] hasRoyalFlush == FALSE
2013-03-14 10:27:53.522 TexasHoldemGame[7600:c07] Player has a straight.
2013-03-14 10:27:53.523 TexasHoldemGame[7600:c07] Player has a flush.

And, as you can imagine, on screen two UIAlertViews pop up, the "STRAIGHT" and "FLUSH" alertviews. I've tried the above method for isStraightFlush and another one: create a temporary array within the method, store the receiving array in the gameplay layer in the temporary array, disperse the cards by suit into four individual arrays (clubArray, diamondArray, heartArray, spadeArray), and then iterating through the arrays to see if the cards are in sequential order, much as I did above. If the arrays have less than 5 cards, then of course, a straight flush is not possible.

I don't know what I'm doing wrong. Sorry for the ridiculously long post. Any help would be appreciated.

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
baptzmoffire
  • 589
  • 2
  • 4
  • 20

1 Answers1

1

The problem is here:

[self sortByRank];
[self sortBySuit];

Those methods don't modify the array in place, but rather return a sorted array, which you then discard.

My suggestion: instead of making a category on NSMutableArray, make a Hand class with an NSMutableArray property called something like cards. Then -sortByRank and -sortBySuit can reassign that property, and in the rest of your logic, replace self with self.cards.

Note: Oops. I see this isn't the problem, as you're sorting by rank and suit before you invoke -isStraightFlush. Still, those lines only serve to confuse.

I'll leave this answer, as my suggestion to build a better model class still stands.

Added: You also shouldn't be doing pointer comparison on NSNumber and NSString objects. That actually could be the problem.

card1.suit == card2.suit
card1.rank == (card2.rank - 1)

Instead compare the values:

[card1.suit isEqualToString:card2.suit]
card1.rank.integerValue == card2.rank.integerValue - 1
paulmelnikow
  • 16,895
  • 8
  • 63
  • 114
  • Thanks, noa. The app is still a work in progress. I may still create a Hand class. For now, I was just putting all that code into my gameplay layer so I get a better understanding of the logic before attempting to make a class for it. This is my first iPhone app/game, and really the first large-scale app I've EVER written, so both the app and I are works in progress. :) Thanks again. – baptzmoffire Mar 14 '13 at 19:09
  • I just noticed another problem which is another likely cause. – paulmelnikow Mar 14 '13 at 19:17
  • I'm not entirely sure that I included all of the possible problematic code. I'm almost positive, but of course, since I don't know what the problem is, it's possible that I'm omitting the problem part. :/ Let me know if you want me to post more. But, again I'm, like, 99% sure the problem would lie nowhere else. – baptzmoffire Mar 14 '13 at 19:35
  • In response to the "added:" portion of your answer, noa: I did try hard-coding everything, cuz I thought my #defines might be the problem, so I tried doing what you said, but using KVC instead of the dot syntax. It was something like **[[[diamondArray objectAtIndex:whatever] valueForKey:@"rank"] intValue] == [[[diamondArray objectAtIndex:whatever + 1] valueForKey:@"rank"] intValue]** and **[[[diamondArray objectAtIndex:whatever] valueForKey:@"suit"] isEqualToString:[[diamondArray objectAtIndex:whatever + 1] valueForKey:@"suit"]]** Let me try again though, just to be safe. – baptzmoffire Mar 14 '13 at 19:42
  • Before editing the comparisons, as you suggested in your added: section, I'm noticing that there are only four cards in my clubArray for my loaded deck. Trying to figure out why now. – baptzmoffire Mar 14 '13 at 20:09
  • If you don't want to use dot notation you can always use message notation: `[card rank]`, `[card suit]`. – paulmelnikow Mar 15 '13 at 00:55