pelsbust
pelsbust

Reputation: 41

Random shuffle seems to produce the same result, but only in the first two instances. How do I avoid this?

I had to program a game of blacjack for class. Everything seems to be working fine, except shuffling the card deck when initializing the game (drawing the first two cards). Everything from then on out seems random.

I'll provide all necessary code. The randomWithLimits-function I am using:

int randomWithLimits(int upperLimit, int lowerLimit)
{
    return (std::rand() % (upperLimit - lowerLimit + 1) + lowerLimit);
}

Simple enough, it is seeded in the main, like this:

int main()
{
    srand(time(nullptr));
    Blackjack bj;
    bool play = true;
    while (play == true) play = bj.playGame();
    return 0;
}

The blackjack function itself is quite long, but here's the part that doesn't work properly (the first round):

bool Blackjack::playGame() {
    CardDeck deck = CardDeck();
    std::cout << "The dealer shuffles the deck\n";
    deck.shuffle();
    drawInitialCards();
    std::cout << "\nYour hand is currently " << playerHand << ".";


    {...}


    std::string cont;
    std::cout << "\n\n\nDo you wish to play another round? (y/n) ";
    std::cin >> cont;
    while (cont != "y" && cont != "n") {
        std::cout << "\nNot a valid choice, choose again: (y/n) ";
        std::cin >> cont;
    }
    if (cont == "y") return true;
    else return false;
}

CardDeck is a class with this function

CardDeck::CardDeck() {
    int count = 0;
    for (int s = CLUBS; s <= SPADES; s++) {
        for (int r = TWO; r <= ACE; r++) {
            Card card(static_cast<Suit>(s), static_cast<Rank>(r));
            cards.push_back(card);
        }
    }
    currentCardIndex = 0;
}

which creates the deck. currentCardIndex keeps track of how many cards have been drawn, s is an enum-type called Suit and r is an enum-type called Rank. This seems to work fine.

It uses this shuffle function,

void CardDeck::shuffle() {
    int count = 0;
    while (count < 100) {
        int a = randomWithLimits(51, 0);
        int b = randomWithLimits(51, 0);
        swap(a, b);
        count++;
    }
}

which uses the randomWithLimits-function from earlier and this swap-function

void CardDeck::swap(int a, int b) {
    Card temp = cards[a];
    cards[a] = cards[b];
    cards[b] = temp;
}

It's not a big issue, but it still bothers me. Whenever I compile and run the function for the first time, the first output is always:

The dealer shuffles the deck

You drew a Two of Clubs.
The dealer drew a card.

You drew a Four of Clubs.
The dealer drew a card.
Your hand is currently 6.

From then every card seems to be random. The draw card function:

Card CardDeck::drawCard() {
    currentCardIndex++;
    return cards[currentCardIndex - 1];
}

The drawInitialCards-function:

void Blackjack::drawInitialCards() {
    Card card = deck.drawCard();
    std::cout << "\nYou drew a " << card.toString() << ".";
    playerHand = getPlayerCardValue(&card);
    card = deck.drawCard();
    std::cout << "\nThe dealer drew a card.";
    dealerHand = getDealerCardValue(&card, dealerHand);
    card = deck.drawCard();
    std::cout << "\n\nYou drew a " << card.toString() << ".";
    playerHand += getPlayerCardValue(&card);
    card = deck.drawCard();
    std::cout << "\nThe dealer drew a card.";
    dealerHand += getDealerCardValue(&card, dealerHand);
}

I've tried messing around with how many times the shuffle-function swaps cards, whether I place the seed in main or the playGame-function etc. but I always get this result. Any help?

Upvotes: 2

Views: 211

Answers (2)

Jason
Jason

Reputation: 1099

Since the first cards you are generating are in fact clubs, starting with the two of clubs, it would seem that the shuffle isn't actually touching the top cards of the deck.

One thing that your current code doesn't guarantee is that every card will be hit in the shuffle. Rather than doing it 100 times to a random pair, try swapping each card with a random one in a loop from card 0 to card 51.

void CardDeck::shuffle() {

    for(int a = 0; a < 52; a++) {
        int b = randomWithLimits(51, 0);
        swap(a, b);
    }
}

This should ensure that every card is touched in the shuffle, and that every location has an equal likelihood of holding any card. Under your previous system there was a high probability that not all cards would be shuffled.

Upvotes: 2

pelsbust
pelsbust

Reputation: 41

Found the mistake. This

bool Blackjack::playGame() {
    CardDeck deck = CardDeck();

should simply be written

bool Blackjack::playGame() {
    deck = CardDeck();

seems that I created a new deck as I thought.

Upvotes: 2

Related Questions