0

I'm writing a C++ program for an introductory course that simulates a poker game. I created a card object with with integers to store a value for face and suit. I then created a DeckOfCards object that has a C++11 array of 52 card objects. I am attempting to assign the cards their values and shuffle the deck in the deckOfCards constructor. After putting it through some tests I believe i've tracked the issue down to this face and suit generation process. I'm also attempting to share these objects with another class (Hand) by returning a reference to these objects in a dealCard() method, but I think the errors are occurring before the hand is instantiated. The error is occurring in GCC on my Arch-Linux VM and in Visual Studio, so it seems to be compiler indepedent (though clang wont even compile it). The Deck's Constructor:

DeckOfCards::DeckOfCards(bool startShuffled) //Constructor.
{
    /************************************************************
    Constructor iterates through the four suits and 13 faces,
    generating a card for each combination. This adds up to a
    deck of 52 unique cards. By default it shuffles the deck to
    prevent accidental usage of an unshuffled deck in a card
    game. Passing 'false' as an arguement prevents the initial
    shuffle.
    ************************************************************/
    int arrayLoc = 0; //The card being initialized (its a subscript of deck).

    for (int i = 0; i < 4; i++) //For each of the four suits.
    {
        for (int j = 0; j < 13; j++) //For each face in that suit.
        {
            deck[arrayLoc].setFace(j); //Create a card with that face.
            deck[arrayLoc].setSuit(i); //And with that suit.
            arrayLoc++; //Then move to the next card.
        }
    }

    currentCard = 0; //Sets the top of the deck.

    if (startShuffled)
        shuffle(); //Shuffles the deck by default.
}

VS2013's debugger is saying it can't read deck[0]'s face and suit data after the first iteration through this loop. It is acting similarly for the rest of them as well. The main program itself (not shown here) is running up to the point where I attempt to deal the cards to a Hand via an array of pointers to the deck, and I think its related to incorrect initialization during deck generation. I can provide more of the code if no one can find a problem with what I have here.

Card's getters/setters:

void Card::setFace(int faceVal)
{
    if (faceVal >= 0 && faceVal < 13) //Validates value before setting.
        face = faceVal; //Sets the value of Card's face.
    else
        throw invalid_argument("Face value must be between 0 and 12 (inclusive)");
}

void Card::setSuit(int suitVal)
{
    if (suitVal >= 0 && suitVal < 4) //Validates value before setting.
        suit = suitVal; //Sets the value of Card's suit.
    else
        throw invalid_argument("Suit value must be between 0 and 3 (inclusive)");
}

//Getters
int Card::getFace() const //Returns face by value.
{
    return face;
}

int Card::getSuit() const //Returns suit by value.
{
    return suit;
}

EDIT: (Adding info) My hand class has an array of five pointers to Card objects, which It retrieves from the deck by calling the DeckOfCard's dealCard() method.

const Card DeckOfCards::dealCard()
{
    /*************************************************
    If the deck has not depreciated, this returns a
    const reference to the card at the top of the deck
    and increments to the next card. If it is depreciated
    it throws an exception.
    *************************************************/
    if (moreCards())
    {
        unsigned int tempCurrentCard = currentCard;
        currentCard++;
        return deck[tempCurrentCard];
    }
    else
    {
        throw invalid_argument("The deck is out of unused cards. Must shuffle to continue.");
    }
}

The Hand's constructor:

Hand::Hand(const Card &card1, const Card &card2, 
    const Card &card3, const Card &card4, const Card &card5)
{
    /*****************************************************
    Constructor initializes a c++11 array of pointers to
    card objects.
    *****************************************************/

    //Initialize the cards in hand. (as pointers)
    cardsInHand[0] = &card1;
    cardsInHand[1] = &card2;
    cardsInHand[2] = &card3;
    cardsInHand[3] = &card4;
    cardsInHand[4] = &card5;

    //Calculate the value of the hand.
    calcHandScore();
}

I'm instantiating the hand in main by using myDeck.dealCard() as each of the arguments in the hand's constructor. This data hand-off seems like a likely place for the error to be.Hand player1(deck.dealCard(), deck.dealCard(), deck.dealCard(), deck.dealCard(), deck.dealCard()); But It could also be related to the shuffling algorithm for the deck:

void DeckOfCards::shuffle()
{
    /***********************************************************
    Shuffles the deck of cards by via a random number generator.
    Should be called whenever the current card is the final
    card in the deck.
    ***********************************************************/
    srand(time(NULL)); //Creates a random seed for number generation.
    int randomValue; //Stores random number for card selection.

    //Loops through each card in deck and swaps it with another.
    for (int i = 0; i < 52; i++) //Iterates through the deck.
    {
        randomValue = rand() % 51; //Selects a random card to swap.

        if (randomValue != i) //Prevents self assignment.
        {
            //Swaps the cards values, effectively swapping their locations.
            int tempFace = deck[randomValue].getFace(); //Holds a copy of selected card.
            int tempSuit = deck[randomValue].getSuit();
            deck[randomValue].setFace(deck[i].getFace());
            deck[randomValue].setSuit(deck[i].getSuit());
            deck[i].setFace(tempFace);
            deck[i].setSuit(tempSuit);
        }
    }

    currentCard = 0; //Shuffle resets the "top" of the deck.
}
  • 4
    What is `deck` and how it is initialized? – juanchopanza Nov 10 '13 at 08:22
  • Deck is an array declared in the header/class definition. I did not explicitly create each card in the deck, so I think they are using the default card constructor. If so they are initializing face and suit to zero. – Hunter Jones Nov 10 '13 at 08:29
  • There's nothing wrong with the code posted. Try and post a minimal but complete program that has this problem. Whatever the error is it's not what you think it is, so try to post a complete program instead of just the parts you think are relevant. – john Nov 10 '13 at 08:36
  • It seems that the constructor does work, and the program fails somewhere later. How are you initializing that `Hand` object? – nullptr Nov 10 '13 at 08:36
  • Just added in the hand's constructor, the handoff of data between the two classes, and some more info on DeckOfCard's implementation. – Hunter Jones Nov 10 '13 at 09:03
  • Consider [this](http://coliru.stacked-crooked.com/a/22eac9866ba9d945) code. In particular - use `std::random_shuffle` instead of hand-crafted loop. And there is no need for getters+setters, if you want to do some runtime check of arguments in something like `Card::setFace`, then - just use special class for `Face` which will establish it's invariants in constructor - and use it as public member in `Card`. – Evgeny Panasyuk Nov 10 '13 at 10:53

1 Answers1

0

This is going to sound stupid but after stepping through the code with the debugger I realized the class logic was all sound. The issue was with a for loop inside another for loop incrementing the wrong variable (ie for (int j = 5; i < 52; j++)).