Hello, OnlineGDB Q&A section lets you put your programming query to fellow community users. Asking a solution for whole assignment is strictly not allowed. You may ask for help where you are stuck. Try to add as much information as possible so that fellow users can know about your problem statement easily.

Can someone help me check my code, the player's score always wrong.

+5 votes
asked May 13 by Diep Ngo (170 points)
/******************************************************************************

*******************************************************************************/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// Implementation of the ADT Card ********************************************

struct Card  // You may use your own implementation instead.
{
    char    rank,       // 2, 3, ..., 9, T, J, Q, K, A
            suit;       // In ascending order: C(lub), D(iamond), H(eart), S(pade)
    int     point,      // Value of numbered card; 10 for face cards, 11 for A.
            order,      // 0 to 51; Aces are high
            rankCode,   // 0 to 12 matching above ranks, respectively.
            suitCode;   // 0 to 4 matching above suits, respectively
};

void display(const Card &c)  // You may use your own implementation instead.
/*
    c will be displayed with two characters.
    For example: 2C will be two of clubs, TH will be ten of hearts.
    
    You may choose to display c differently than described above to suit the
    user interface you designed.
*/
{
    cout << c.rank << c.suit << ' ';
}

// Implementation of the ADT Deck ********************************************

struct Deck{  // You may use your own implementation instead.
    vector<Card> cards;
};

void initialize(Deck &d)  // You may use your own implementation instead.
/*
    The standard 52 cards is ordered by rank and suit, with Aces high,
    from 0 to 51 matching the following
    2C, 2D, 2H, 2S,
    3C, 3D, 3H, 3S,
    ...
    KC, KD, KH, KS,
    AC, AD, AH, AS
*/
{
    d.cards.clear();
    
    Card tempCard;
    for (int order = 0; order < 52; order++)
    {
        // Assign order
        tempCard.order = order;
        
        // Assign suitCode, cuit
        int suitCode = order % 4;  // 0, 1, 2, 3 for C(lub), D(iamond), H(eart), S(pade)
        tempCard.suitCode = suitCode;
        switch (suitCode)
        {
            case 0: tempCard.suit = 'C'; break;
            case 1: tempCard.suit = 'D'; break;
            case 2: tempCard.suit = 'H'; break;
            case 3: tempCard.suit = 'S'; break;
        }
        
        // Assign rankCode, rank, point
        int rankCode = order / 4;  // 0, ..., 12 for 2, ..., 9, T, J, Q, K, A
        tempCard.rankCode = rankCode;
        if (rankCode == 12)
        {   // The code represents A
            tempCard.rank = 'A';
            tempCard.point = 11;
        }
        else if (rankCode <= 7)
        {   // The codes 0 to 7 represent ranks 2 to 9
            tempCard.point = rankCode;
            tempCard.rank = static_cast<char>('0' + rankCode + 2);
        }
        else
        {
            // Code represents a 10-point Card
            tempCard.point = 10;
            switch(rankCode)
            {
                case 8:  tempCard.rank = 'T'; break;
                case 9:  tempCard.rank = 'J'; break;
                case 10: tempCard.rank = 'Q'; break;
                case 11: tempCard.rank = 'K'; break;
            }
        }
        d.cards.push_back(tempCard);         
    }
}

void shuffle(Deck& d)
/*
    The cards in d is shuffled.
*/
{
    int n = d.cards.size();
    srand(time(NULL)); // Seed the random number generator

    for (int i = 0; i < n; i++) {
        int j = rand() % n; // Generate a random index

        // Swap cards at index i and j
        Card temp = d.cards[i];
        d.cards[i] = d.cards[j];
        d.cards[j] = temp;
    }
}

Card deal(Deck& d)
/*  
    This function removes and returns the last element of d.cards.
    
    Be sure to read Ch. 11.8 p. 634 about returning a structure from a function.
    Use the vector method pop_back if you are using a vector to implement Deck.
    Review Program 7-29 on p. 444 to see the methods pop_back and push_back
    in action.
*/
{
     if (d.cards.empty()) {
        throw runtime_error("Cannot deal a card from an empty deck");
    }
    Card c = d.cards.back();
    d.cards.pop_back();
    return c;
    
}

void display(const Deck &d)  // You may use your own implementation instead.
{
    for (int k = 0; k < 52; k++)
    {
        display(d.cards[k]);
        cout << ' ';
    }
    cout << endl;
}

// Implementation of the ADT Hand *********************************************

struct Hand  // You may use your own implementation instead.
{
    vector<Card> cards;
};

void initialize(Hand& h)
/*
    Clear the hand h so that h contains no cards.
*/
{
    h.cards.clear();
}

int getPoints(const Hand &h)
/*
    Returns the total number of points of all the cards inthe hand h.
*/
{
    int points = 0;
    int numAces = 0;
    
    for (const auto& card : h.cards) {
        points += card.point;
        if (card.rank == 'A') {
            numAces++;
        }
    }
    
    // Adjust ace values to minimize the total score
    while (numAces > 0 && points > 21) {
        points -= 10;  // Treat Ace as 1 instead of 11
        numAces--;
    }
    
    return points;
    
}

void addCard(Hand& h, const Card& c)
/*
    Add the card c to the hand h.
*/
{
    h.cards.push_back(c);
}

void displayHands(bool showHole, const Hand& d, const Hand& p)
/*
    This function displays the cards in the dealer's and player's hands, as well as the number of points for each hand.
    When showhole is false, the dealer's hole is not displayed.
*/
{
     cout << "Dealer's hand: ";
    for (int i = 0; i < d.cards.size(); i++) {
        if (i == 0 &&!showHole) {
            cout << "X ";
        } else {
            display(d.cards[i]);
            cout << ' ';
        }
    }
    cout << endl;
    cout << "Player's hand: ";
    for (const auto& card : p.cards) {
        display(card);
        cout << ' ';
    }
    cout << endl;
    
}

void playerTurn(Hand& p, const Hand& d)
{
    while (true)
    {
        int pScore = getPoints(p);
        if (pScore == 21)
        {
            cout << "Player has Blackjack! You win!" << endl;
            return;
        }
        if (pScore > 21)
        {
            cout << "Player busts! Dealer wins." << endl;
            return;
        }
        char choice;
        cout << "Do you want to hit or stand? (h/s): ";
        cin >> choice;
        if (choice == 'h')
        {
            addCard(p, deal(playdeck));
            displayHands(false, d, p);
        }
        else if (choice == 's')
        {
            break;
        }
        else
        {
            cout << "Invalid input. Please enter 'h' or 's'." << endl;
        }
    }
}

void dealerTurn(Hand& d, const Hand& p, Deck& playdeck) {
    while (getPoints(d) < 17) {
        addCard(d, deal(playdeck));
    }
    displayHands(true, d, p);
}

void decideWinner(const Hand& d, const Hand& p) {
    int playerScore = getPoints(p);
    int dealerScore = getPoints(d);

    if (playerScore > 21) {
        cout << "Dealer wins (Player Loss Because Player Score is exceeding 21)" << endl;
    } else if (dealerScore > 21) {
        cout << "Player wins (Dealer Loss Because Dealer Score is exceeding 21)" << endl;
    } else if (playerScore > dealerScore) {
        cout << "Player wins" << endl;
    } else if (playerScore < dealerScore) {
        cout << "Dealer wins" << endl;
    } else {
        cout << "It's a tie!" << endl;
    }
}

//***************************************************************************

int main()
{
    Hand player, dealer;
    Deck playdeck;
    
    initialize(playdeck);
    // display(playdeck);  // This line needs to be commented out;
                        // only here for testing initalize(playdeck)
    shuffle(playdeck);

    initialize(dealer);
    initialize(player);
    for (int k = 1; k<=2; k++)
    {
        addCard(player, deal(playdeck));
        addCard(dealer, deal(playdeck));
    }
    
    displayHands(false, dealer, player);
    playerTurn(player, dealer);
    dealerTurn(dealer, player);
    decideWinner(dealer, player);

    return 0;
}

1 Answer

+1 vote
answered May 14 by Peter Minarik (88,520 points)
edited May 15 by Peter Minarik

Hi Diep Ngo,

I had a look at your code, but unfortunately, it does not even compile.

It's a bit long code, so it would be nice if you could make it compile before you ask for help finding incorrect behaviour. It could take someone quite a lot of time to fix an unknown code (especially logic and not simple typos).

However, I took some time to fix up your code so it would at least compile. I needed to add the Deck& to the argument list of playerTurn() function just like dealerTurn() has it. This way the code runs. I also needed to pass the playDeck to both of these functions when invoked from the main.

Now I had the opportunity to test it and see what the issue is.

It looks like the initialise(Deck&) function is bugged. If I modify the code so it would print all the info about the cards I can see that the points assigned to the cards are wrong. The points assigned to a card shouldn't be rankCode, but rankCode + 2.

With this fix, the points calculation should be fine.

        else if (rankCode <= 7)
        {   // The codes 0 to 7 represent ranks 2 to 9
            tempCard.point = rankCode + 2;
            tempCard.rank = static_cast<char>('0' + rankCode + 2);
        }

Good luck!

Welcome to OnlineGDB Q&A, where you can ask questions related to programming and OnlineGDB IDE and and receive answers from other members of the community.
...