SOLVED - Error message in 'C' program

70 Tango Charlie

Well-Known Member
Joined
Oct 7, 2019
Messages
523
Reaction score
676
Credits
2,064
Hi Guys and Gals,
First, my specs.
fzx.png


Next up, background.
I've been studying the C programming language a little bit. Got the basics down pretty good.
Then I went into a sample Poker program and copied the source code.
When I tried to compile it with gcc I got this error message:
poker.png


Here's my copy:
poker-a.png


My question is: what is wrong with this and how do I fix it.
If I read this error message right, it is telling me that I need to insert 'while' in front of 'int analyzeHand'. I tried it, but it got worse.
Am I mis-reading this error message?
Thanks for any help.
OG TC
 


I can't scroll your 'code' example - did you upload an image?
At the top of the text entry, on the far right, you'll see '...'. Select this, then '</> code' to insert code, then insert your actual code, not an image....

keith
 
@khedger
Yes I did use an image.
C:
// Example poker program from Appendix B of Absolute Beginner's
// Guide to C, 3rd Edition
// File AppendixBpoker.c

    /* This program plays draw poker. Users can play as often as they
want, betting between 1 and 5. They are dealt 5 cards and then get
to choose which cards to keep, and which cards to replace. The new
hand is then reviewed and the user's payout is set based on the
value of the hand. The user's new bankroll is displayed as they are
given the option to continue. */

    // Header files

#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <stdlib.h>

// Two constants defined for determining whether hands ar flushes
// or straights

#define FALSE 0
#define TRUE 1

// Function prototyping

void printGreeting();
int getBet();
char getSuit(int suit);
char getRank(int rank);

void getFirstHand(int cardRank[], int cardSuit[]);
void getFinalHand(int cardRank[], int cardSuit[], int finalRank[],
            int finalSuit[], int ranksinHand[],
            int suitsinHand[]);
int analyzeHand(int ranksinHand[], int suitsinHand[]);


int main()

{
    int bet;
    int bank = 100;
    int i;
    int cardRank[5]; //Will be one of 13 values (Ace-King)
    int cardSuit[5]; //Will be one of 4 values (for Clubs, Diamonds,
                        // Hearts, Spades)

    int finalRank[5];
    int finalSuit[5];

    int ranksinHand[13];  //Used for evaluating the final hand
    int suitsinHand[4];   //Used for evaluating the final hand

    int winnings;
    time_t t;
    char suit, rank, stillPlay;

    //This function is called outside the do...while loop because
    //the greeting
    //only needs to be displayed once, while everything else in main
    //will run
    //multiple times, depending on how many times the user wants to
    //play.

    printGreeting();
                    //Loop runs each time the user plays a hand of draw poker

    do {
        bet = getBet();

        srand(time(&t));
        getFirstHand(cardRank, cardSuit);

        printf("Your five cards: \n");
        for (i = 0; i <5; i++)

    {
            suit = getSuit(cardSuit[i]);
            rank = getRank(cardRank[i]);
            printf("Card #%d: %c%c\n", i+1, rank, suit);
    }

        // These two arrays are used to figure out the value of
        // the players' hand. However, they must be zeroed out
        // in case the user plays multiple hands.

    for (i=0; i < 13; i++)
    {
        ranksinHand[i] = 0;
    }


    getFinalHand(cardRank, cardSuit, finalRank, finalSuit,
                            ranksinHand, suitsinHand);

    printf("Your five final cards: \n");
    for (i = 0; i < 5; i++)

    {
        suit = getSuit(finalSuit[i]);
        rank = getRank(finalRank[i]);
        printf("Card #%d: %c%c\n", i+1, rank, suit);
    }

        winnings = analyzeHand(ranksinHand, suitsinHand);
        printf("You won %d!\n", bet*winnings);
        bank = bank - bet + (bet*winnings);
        printf("\nYour bank is now %d.\n", bank);
        printf("\nDo you want to play again? ");
        scanf(" %c", &stillPlay);

    } while (toupper(stillPlay) == 'Y');

        return 0;
    }

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

    // Print a quick greeting as well as tell the users the value of
    // different winning hands

    void printGreeting()
    {
        printf("*****************************************************\n");
        printf("\n\n\tWelcome to the Absolute Beginners' Casino\n\n");
        printf("\tHome of Video Draw Poker\n\n");
        printf("*****************************************************\n");

        printf("Here are the rules:\n");
        printf("You start with 100 credits, and you make a bet from ");
        printf("1 to 5 credits.\n");
        printf("You are dealt 5 cards, and you then choose which ");
        printf("cards to keep ");
        printf("or discard.\n");
        printf("You want to make the best possible hand.\n");
        printf("\nHere is the table for winnings (assuming a ");
        printf("bet of 1 credit):");
        printf("\nPair\t\t\t\t1 credit");
        printf("\nTwo pairs\t\t\t2 credits");
        printf("\nThree of a kind\t\t\t3 credits");
        printf("\nStraight\t\t\t4 credits");
        printf("\nFlush\t\t\t\t5 credits");
        printf("\nFull House\t\t\t8 credits");
        printf("\nFour of a Kind\t\t\t10 credits");
        printf("\nStraight Flush\t\t\t20 credits");
        printf("\n\nHave fun!!\n\n");
    }


// Function to deal the first five cards

    void getFirstHand(int cardRank[], int cardSuit[])

    {
        int i,j;
        int cardDup;

        for (i=0; i < 5; i++)
            {

                cardDup = 0;
                do {
                    // Card rank is one of 13 (2-10, J, Q, K, A)
                    cardRank[i] = (rand() % 13);
                    // Card suit is one of 4
                    // (club, diamond, heart, spade)
                    cardSuit[i] = (rand() % 4);

                    // Loop that ensures each card is unique
                    for (j=0; j < i; j++)
                {
                    if ((cardRank[i] == cardRank[j]) &&
                    (cardSuit[i]))
                {
                    cardDup = 1;
                }

            }
        } while (cardDup == 1);
    }
}

// Function that changes the suit integer value to a character
// representing the suit

    char getSuit(int suit)
    {
        switch (suit)
        {

            case 0:
                return('c');
            case 1:
                return('d');
            case 2:
                return('h');
            case 3:
                return('s');
        }
    }

// Function that changes the rank integer value to a character
// representing the rank

char getRank(int rank)
    {
        switch (rank)
        {
            case 0:
                return('A');
            case 1:
                return('2');
            case 2:
                return('3');
            case 3:
                return('4');
            case 4:
                return('5');
            case 5:
                return('6');
            case 6:
                return('7');
            case 7:
                return('8');
            case 8:
                return('9');
            case 9:
                return('T');
            case 10:
                return('J');
            case 11:
                return('Q');
            case 12:
                return('K');
        }
    }

// Function to get the users' bet between 1 and 5

int getBet()
    {
        int bet;

        do //Will keep running until the user enters 0-5
        {
            printf("How much do you want to bet? (Enter a number ");
            printf("1 to 5, or 0 to quit the game): ");
            scanf(" %d", &bet);

            if (bet >= 1 && bet <= 5)
            {
                return(bet);
            }
            else if (bet == 0)
            {
                exit(1);
            }
            else
            {
                printf("\n\nPlease enter a bet from 1-5 or ");
                printf("0 to quit the game.\n");
            }
        }

    // Last function revviews the final hand and determines the value of
    // the hand.

    int analyzeHand(int ranksinHand[], int suitsinHand[])
    {
        int num_consec = 0;
        int i, rank, suit;
        int straight = false;
        int flush = false;
        int four = false;
        int three = false;
        int pairs = 0;

        for (suit = 0; suit < 4; suit++)
            if (suitsinHand[suit] == 5)
                fluush = TRUE;
        rank = 0;
        while (ranksinHand[rank] == 0)
            rank++;
        for (; rank < 13 && ranksinHand[rank]; rank++)
            num_consec++;
        if (num_consec == 5)    {
            straight = TRUE;
        }
        for (rank = 0; rank < 13; rank++) {
            if (ranksinHand[rank] == 4)
                four = TRUE;
            if (ranksinHand[rank] == 3)
                three = TRUE;
            if (ranksinHand[rank] == 2)
                pairs++;
        }

        if (straight && flush) {
            printf("Straight flush\n\n");
            return (20);
        }
        else if (four) {
            printf("Four of a kind\n\n");
            return (10);
        }
        else if (three && pairs == 1) {
            printf("Full house\n\n");
            return (8);
        }
        else if (flush) {
            printf("Flush\n\n");
            return (5);
        {
        else if (straight) {
            printf("Straight\n\n");
            return (4);
        }
        else if (three) {
            printf("Three of a kind\n\n");
            return (3);
        }
        else if (pairs == 2) {
            printf("Two pairs\n\n");
            return (2);
        }
        else if (pairs == 1) {
            printf("Pair\n\n");
            return (1);
        }
        else {
            printf("High Card\n\n");
            return (0);
        }
    }

    // This function looks through each of the five cards in the first hand
    // and asks the user if they want to keep the card. If they say no,
    // they get a replacement card.

    void getFinalHand(int cardRank[], int cardSuit[], int finalRank[],
            int finalSuit[], int ranksinHand[],
            int suitsinHand[])

    {
        int i, j, cardDup;
        char suit, rank, ans;

        for (i=0; i < 5; i++)
    {
        suit = getSuit(cardSuit[i]);
        rank = getRank(cardRank[i]);
        printf("Do you want to keep card #%d: %c%c?", i+1, rank, suit);
        printf("\nPlease answer (Y/N): ");
        scanf(" %c", &ans);
        if (toupper(ans) == 'Y')
        {
            finalRank[i] = cardRank[i];
            finalSuit[i] = cardSuit[i];
            ranksinHand[finalRank[i]]++;
            suitsinHand[finalSuit[i]]++;
            continue;
        }
        else if (toupper(ans) == 'N')
        {
            cardDup = 0;
            do {
                cardDup = 0;
                finalRank[i] = (rand() % 13);
                finalSuit[i] = (rand() % 4);

    // First check your new card against the 5 original
    // cards to avoid duplication
    for (j=0; j < 5; j++)
    {
        if ((finalRank[i] == cardRank[j]) &&
        (finalSuit[i] == cardSuit[j]))
    {
        if ((finalRank[i] == cardRank[j]) &&
        (finalSuit[i] == cardSuit[j]))
        {
            cardDup = 1;
        }
    }

    // Next, check the new card against any newly drawn
    // cards to avoid duplication
    for (j=0; j < i; j++)
    {
        if ((finalRank[i] == finalRank[j]) &&
        (finalSuit[i] == finalSuit[j]))
        {
            cardDup = 1;
                        }
                    }

                }   while (cardDup == 1);
                    ranksinHand[finalRank[i]]++;
                    suitsinHand[finalSuit[i]]++;
            }
        }
    }
            


Thanks for the lesson in how to insert stuff.
I am constantly learning. It is indeed fun.
Thanks again.

Now, maybe you can tell me what my problem is with this error message.
OG TC
 
I'm not an experienced C programmer, but it looks to me like you're missing a closing '}' for the getbet function.

Code:
            {
                printf("\n\nPlease enter a bet from 1-5 or ");
                printf("0 to quit the game.\n");
            }
        }
    } <----- don't you need another '}' here????


keith
 
There are a number of very, very minor problems in your code @70 Tango Charlie.

Most of them look like simple typos. If you manually typed the code, then you may easily have accidentally skipped a line, or misread something - or just made a simple typo.

Most of the problems are brace { } related. There were a few closing braces that were missing.

In the nested if..else if...else... block of code in your analyzeHand function, there is one place where you put an opening brace { where there should have been a closing brace }.

There is a spelling mistake/typo for one of your variables - fluush should be flush

The do loop in your getBet function was missing a matching while statement.
Looking at the logic, this will probably just be a case of adding while(true); AFTER the closing brace } for the do loop.

Also, there were some integer variables declared in your analyzeHand function (see straight, flush, four and three) that were being set to false the C compiler doesn't know what false is. So there is a type mismatch there.

Historically C didn't have a bool type, so TRUE and FALSE are macros that are typically defined as 1 and 0, respectively - as you have done at the top of your file.
And it IS possible to set integer variables to TRUE or FALSE.
So, you could fix the problem by keeping those variables as int and changing the instances of false to FALSE.

However - in C99 and onwards, you are encouraged to use the bool type from stdbool.h for booleans.

So personally, I'd remove the #definitions of TRUE and FALSE at the top of the file, change those few int variables to bool and replace all other instances of TRUE and FALSE with true or false, respectively.
And don't forget, in order to use booleans in your C code, you will also need to include stdbool.h.

But you could just as equally use the previous fix I mentioned - changing all instances of false to FALSE. Either will fix the problem.

To avoid any confusion here, I'll post two slightly cleaned up versions of your code with matching braces. I've put some comments in where I've made changes.

I've also formatted the code so that the opening and closing braces are always on their own line.
e.g.
Like this:
C:
if (something)
{
    // do something
}
else
{
    // do something else
}

The reason for this is because it makes it easier for you to see exactly where each block of code begins and ends.
So as a beginner programmer, formatting the braces like this gives you a more obvious visual clue as to which braces are matched up.
The obvious downside to it is that you have a lot of lines that just contain braces.

If you use the java style braces where the opening brace:
C:
if (something) {
  // do something
}
else {
  //do something else
}
Yes, it's more compact. You're not wasting an entire line just for an opening brace. But when you have multiple nested conditionals, inside nested loops inside a function etc - the braces can sometimes get a bit confusing. So for now, I'd recommend formatting your braces like the first example, not the second one.

And I'd definitely try to avoid trying to mix the two styles.

Once you get more experienced - feel free to switch to the more compact Java style braces.
BTW - The reason I call it "Java style" is because the Java programming language expects you to use braces like this. But both styles of bracing have been used in C since time immemorial, long before Java existed. And many C programmers have argued about the pro's and cons of each style.
But again, for a beginner - I'd always recommend using the first style!

Anyway - without further ado, here's your code, with some minor corrections and comments from myself.

And again, I've posted two versions:

The first uses the first fix for the boolean related problem:
C:
// Example poker program from Appendix B of Absolute Beginner's
// Guide to C, 3rd Edition
// File AppendixBpoker.c

/* This program plays draw poker. Users can play as often as they
   want, betting between 1 and 5. They are dealt 5 cards and then get
   to choose which cards to keep, and which cards to replace. The new
   hand is then reviewed and the user's payout is set based on the
   value of the hand. The user's new bankroll is displayed as they are
   given the option to continue. */

// Header files
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <stdlib.h>

// Two constants defined for determining whether hands ar flushes
// or straights
#define FALSE 0
#define TRUE 1

// Function prototyping
void printGreeting();
int getBet();
char getSuit(int suit);
char getRank(int rank);

void getFirstHand(int cardRank[], int cardSuit[]);
void getFinalHand(int cardRank[], int cardSuit[], int finalRank[],
int finalSuit[], int ranksinHand[],
int suitsinHand[]);
int analyzeHand(int ranksinHand[], int suitsinHand[]);


int main()
{
    int bet;
    int bank = 100;
    int i;
    int cardRank[5]; //Will be one of 13 values (Ace-King)
    int cardSuit[5]; //Will be one of 4 values (for Clubs, Diamonds,
    // Hearts, Spades)

    int finalRank[5];
    int finalSuit[5];

    int ranksinHand[13];  //Used for evaluating the final hand
    int suitsinHand[4];   //Used for evaluating the final hand

    int winnings;
    time_t t;
    char suit, rank, stillPlay;

    //This function is called outside the do...while loop because
    //the greeting
    //only needs to be displayed once, while everything else in main
    //will run
    //multiple times, depending on how many times the user wants to
    //play.

    printGreeting();
    //Loop runs each time the user plays a hand of draw poker

    do
    {
        bet = getBet();

        srand(time(&t));
        getFirstHand(cardRank, cardSuit);

        printf("Your five cards: \n");
        for (i = 0; i <5; i++)
        {
            suit = getSuit(cardSuit[i]);
            rank = getRank(cardRank[i]);
            printf("Card #%d: %c%c\n", i+1, rank, suit);
        }

        // These two arrays are used to figure out the value of
        // the players' hand. However, they must be zeroed out
        // in case the user plays multiple hands.
        for (i=0; i < 13; i++)
        {
            ranksinHand[i] = 0;
        }


        getFinalHand(cardRank, cardSuit, finalRank, finalSuit,
                ranksinHand, suitsinHand);

        printf("Your five final cards: \n");
        for (i = 0; i < 5; i++)
        {
            suit = getSuit(finalSuit[i]);
            rank = getRank(finalRank[i]);
            printf("Card #%d: %c%c\n", i+1, rank, suit);
        }

        winnings = analyzeHand(ranksinHand, suitsinHand);
        printf("You won %d!\n", bet*winnings);
        bank = bank - bet + (bet*winnings);
        printf("\nYour bank is now %d.\n", bank);
        printf("\nDo you want to play again? ");
        scanf(" %c", &stillPlay);

    } while (toupper(stillPlay) == 'Y');

    return 0;
}

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

// Print a quick greeting as well as tell the users the value of
// different winning hands
void printGreeting()
{
    printf("*****************************************************\n");
    printf("\n\n\tWelcome to the Absolute Beginners' Casino\n\n");
    printf("\tHome of Video Draw Poker\n\n");
    printf("*****************************************************\n");

    printf("Here are the rules:\n");
    printf("You start with 100 credits, and you make a bet from ");
    printf("1 to 5 credits.\n");
    printf("You are dealt 5 cards, and you then choose which ");
    printf("cards to keep ");
    printf("or discard.\n");
    printf("You want to make the best possible hand.\n");
    printf("\nHere is the table for winnings (assuming a ");
    printf("bet of 1 credit):");
    printf("\nPair\t\t\t\t1 credit");
    printf("\nTwo pairs\t\t\t2 credits");
    printf("\nThree of a kind\t\t\t3 credits");
    printf("\nStraight\t\t\t4 credits");
    printf("\nFlush\t\t\t\t5 credits");
    printf("\nFull House\t\t\t8 credits");
    printf("\nFour of a Kind\t\t\t10 credits");
    printf("\nStraight Flush\t\t\t20 credits");
    printf("\n\nHave fun!!\n\n");
}


// Function to deal the first five cards
void getFirstHand(int cardRank[], int cardSuit[])
{
    int i,j;
    int cardDup;

    for (i=0; i < 5; i++)
    {

        cardDup = 0;
        do {
            // Card rank is one of 13 (2-10, J, Q, K, A)
            cardRank[i] = (rand() % 13);
            // Card suit is one of 4
            // (club, diamond, heart, spade)
            cardSuit[i] = (rand() % 4);

            // Loop that ensures each card is unique
            for (j=0; j < i; j++)
            {
                if ((cardRank[i] == cardRank[j]) &&
                        (cardSuit[i]))
                {
                    cardDup = 1;
                }

            }
        } while (cardDup == 1);
    }
}

// Function that changes the suit integer value to a character
// representing the suit

char getSuit(int suit)
{
    switch (suit)
    {

        case 0:
            return('c');
        case 1:
            return('d');
        case 2:
            return('h');
        case 3:
            return('s');
    }
}

// Function that changes the rank integer value to a character
// representing the rank

char getRank(int rank)
{
    switch (rank)
    {
        case 0:
            return('A');
        case 1:
            return('2');
        case 2:
            return('3');
        case 3:
            return('4');
        case 4:
            return('5');
        case 5:
            return('6');
        case 6:
            return('7');
        case 7:
            return('8');
        case 8:
            return('9');
        case 9:
            return('T');
        case 10:
            return('J');
        case 11:
            return('Q');
        case 12:
            return('K');
    }
}

// Function to get the users' bet between 1 and 5
int getBet()
{
    int bet;

    do //Will keep running until the user enters 0-5
    {
        printf("How much do you want to bet? (Enter a number ");
        printf("1 to 5, or 0 to quit the game): ");
        scanf(" %d", &bet);

        if (bet >= 1 && bet <= 5)
        {
            return(bet);
        }
        else if (bet == 0)
        {
            exit(1);
        }
        else
        {
            printf("\n\nPlease enter a bet from 1-5 or ");
            printf("0 to quit the game.\n");
        }
    } while (TRUE); // From Jas - Missing a while clause here! I've just guessed it!
} // From Jas - This closing brace was missing!

// Last function reviews the final hand and determines the value of
// the hand.
int analyzeHand(int ranksinHand[], int suitsinHand[])
{
    int num_consec = 0;
    int i, rank, suit;
    int straight = FALSE; // From Jas - this should be FALSE NOT false
    int flush = FALSE; // From Jas - FALSE NOT false
    int four = FALSE; // From Jas - FALSE NOT false
    int three = FALSE; // From Jas - FALSE NOT false
    int pairs = 0;

    for (suit = 0; suit < 4; suit++)
        if (suitsinHand[suit] == 5)
            flush = TRUE; // From Jas - there was a typo here. should be flush, not fluush!
    rank = 0;
    while (ranksinHand[rank] == 0)
        rank++;
    for (; rank < 13 && ranksinHand[rank]; rank++)
        num_consec++;
    if (num_consec == 5)
        straight = TRUE;

    for (rank = 0; rank < 13; rank++)
    {
        if (ranksinHand[rank] == 4)
            four = TRUE;
        if (ranksinHand[rank] == 3)
            three = TRUE;
        if (ranksinHand[rank] == 2)
            pairs++;
    }

    if (straight && flush)
       {
        printf("Straight flush\n\n");
        return (20);
    }
    else if (four)
    {
        printf("Four of a kind\n\n");
        return (10);
    }
    else if (three && pairs == 1)
    {
        printf("Full house\n\n");
        return (8);
    }
    else if (flush)
       {
        printf("Flush\n\n");
        return (5);
    } // From Jas - This was an open brace, it needed to be a closed brace
    else if (straight)
    {
        printf("Straight\n\n");
        return (4);
    }
    else if (three)
    {
        printf("Three of a kind\n\n");
        return (3);
    }
    else if (pairs == 2)
    {
        printf("Two pairs\n\n");
        return (2);
    }
    else if (pairs == 1)
       {
        printf("Pair\n\n");
        return (1);
    }
    else
       {
        printf("High Card\n\n");
        return (0);
    }
}

// This function looks through each of the five cards in the first hand
// and asks the user if they want to keep the card. If they say no,
// they get a replacement card.
void getFinalHand(int cardRank[], int cardSuit[], int finalRank[],
        int finalSuit[], int ranksinHand[],
        int suitsinHand[])
{
    int i, j, cardDup;
    char suit, rank, ans;

    for (i=0; i < 5; i++)
    {
        suit = getSuit(cardSuit[i]);
        rank = getRank(cardRank[i]);
        printf("Do you want to keep card #%d: %c%c?", i+1, rank, suit);
        printf("\nPlease answer (Y/N): ");
        scanf(" %c", &ans);
        if (toupper(ans) == 'Y')
        {
            finalRank[i] = cardRank[i];
            finalSuit[i] = cardSuit[i];
            ranksinHand[finalRank[i]]++;
            suitsinHand[finalSuit[i]]++;
            continue;
        }
        else if (toupper(ans) == 'N')
        {
            cardDup = 0;
            do
            {
                cardDup = 0;
                finalRank[i] = (rand() % 13);
                finalSuit[i] = (rand() % 4);

                // First check your new card against the 5 original
                // cards to avoid duplication
                for (j=0; j < 5; j++)
                {
                    if ((finalRank[i] == cardRank[j]) &&
                            (finalSuit[i] == cardSuit[j]))
                    {
                        if ((finalRank[i] == cardRank[j]) &&
                                (finalSuit[i] == cardSuit[j]))
                        {
                            cardDup = 1;
                        }
                    }
                } // From Jas - there was a missing closing brace here!

                // Next, check the new card against any newly drawn
                // cards to avoid duplication
                for (j=0; j < i; j++)
                {
                    if ((finalRank[i] == finalRank[j]) &&
                            (finalSuit[i] == finalSuit[j]))
                    {
                        cardDup = 1;
                    }
                }

            } while (cardDup == 1);
            ranksinHand[finalRank[i]]++;
            suitsinHand[finalSuit[i]]++;
        }
    }
}

The second uses stdbool to provide the bool primitive datatype. So instead of using TRUE or FALSE in integer (int) variables, we can use true, or false in boolean (bool) variables:
C:
// Example poker program from Appendix B of Absolute Beginner's
// Guide to C, 3rd Edition
// File AppendixBpoker.c

/* This program plays draw poker. Users can play as often as they
   want, betting between 1 and 5. They are dealt 5 cards and then get
   to choose which cards to keep, and which cards to replace. The new
   hand is then reviewed and the user's payout is set based on the
   value of the hand. The user's new bankroll is displayed as they are
   given the option to continue. */

// Header files
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdbool.h> // From Jas - include stdbool to use bool type

// Function prototyping
void printGreeting();
int getBet();
char getSuit(int suit);
char getRank(int rank);

void getFirstHand(int cardRank[], int cardSuit[]);
void getFinalHand(int cardRank[], int cardSuit[], int finalRank[],
int finalSuit[], int ranksinHand[],
int suitsinHand[]);
int analyzeHand(int ranksinHand[], int suitsinHand[]);


int main()
{
    int bet;
    int bank = 100;
    int i;
    int cardRank[5]; //Will be one of 13 values (Ace-King)
    int cardSuit[5]; //Will be one of 4 values (for Clubs, Diamonds,
    // Hearts, Spades)

    int finalRank[5];
    int finalSuit[5];

    int ranksinHand[13];  //Used for evaluating the final hand
    int suitsinHand[4];   //Used for evaluating the final hand

    int winnings;
    time_t t;
    char suit, rank, stillPlay;

    //This function is called outside the do...while loop because
    //the greeting
    //only needs to be displayed once, while everything else in main
    //will run
    //multiple times, depending on how many times the user wants to
    //play.

    printGreeting();
    //Loop runs each time the user plays a hand of draw poker

    do
    {
        bet = getBet();

        srand(time(&t));
        getFirstHand(cardRank, cardSuit);

        printf("Your five cards: \n");
        for (i = 0; i <5; i++)
        {
            suit = getSuit(cardSuit[i]);
            rank = getRank(cardRank[i]);
            printf("Card #%d: %c%c\n", i+1, rank, suit);
        }

        // These two arrays are used to figure out the value of
        // the players' hand. However, they must be zeroed out
        // in case the user plays multiple hands.
        for (i=0; i < 13; i++)
        {
            ranksinHand[i] = 0;
        }


        getFinalHand(cardRank, cardSuit, finalRank, finalSuit,
                ranksinHand, suitsinHand);

        printf("Your five final cards: \n");
        for (i = 0; i < 5; i++)
        {
            suit = getSuit(finalSuit[i]);
            rank = getRank(finalRank[i]);
            printf("Card #%d: %c%c\n", i+1, rank, suit);
        }

        winnings = analyzeHand(ranksinHand, suitsinHand);
        printf("You won %d!\n", bet*winnings);
        bank = bank - bet + (bet*winnings);
        printf("\nYour bank is now %d.\n", bank);
        printf("\nDo you want to play again? ");
        scanf(" %c", &stillPlay);

    } while (toupper(stillPlay) == 'Y');

    return 0;
}

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

// Print a quick greeting as well as tell the users the value of
// different winning hands
void printGreeting()
{
    printf("*****************************************************\n");
    printf("\n\n\tWelcome to the Absolute Beginners' Casino\n\n");
    printf("\tHome of Video Draw Poker\n\n");
    printf("*****************************************************\n");

    printf("Here are the rules:\n");
    printf("You start with 100 credits, and you make a bet from ");
    printf("1 to 5 credits.\n");
    printf("You are dealt 5 cards, and you then choose which ");
    printf("cards to keep ");
    printf("or discard.\n");
    printf("You want to make the best possible hand.\n");
    printf("\nHere is the table for winnings (assuming a ");
    printf("bet of 1 credit):");
    printf("\nPair\t\t\t\t1 credit");
    printf("\nTwo pairs\t\t\t2 credits");
    printf("\nThree of a kind\t\t\t3 credits");
    printf("\nStraight\t\t\t4 credits");
    printf("\nFlush\t\t\t\t5 credits");
    printf("\nFull House\t\t\t8 credits");
    printf("\nFour of a Kind\t\t\t10 credits");
    printf("\nStraight Flush\t\t\t20 credits");
    printf("\n\nHave fun!!\n\n");
}


// Function to deal the first five cards
void getFirstHand(int cardRank[], int cardSuit[])
{
    int i,j;
    int cardDup;

    for (i=0; i < 5; i++)
    {

        cardDup = 0;
        do {
            // Card rank is one of 13 (2-10, J, Q, K, A)
            cardRank[i] = (rand() % 13);
            // Card suit is one of 4
            // (club, diamond, heart, spade)
            cardSuit[i] = (rand() % 4);

            // Loop that ensures each card is unique
            for (j=0; j < i; j++)
            {
                if ((cardRank[i] == cardRank[j]) &&
                        (cardSuit[i]))
                {
                    cardDup = 1;
                }

            }
        } while (cardDup == 1);
    }
}

// Function that changes the suit integer value to a character
// representing the suit

char getSuit(int suit)
{
    switch (suit)
    {

        case 0:
            return('c');
        case 1:
            return('d');
        case 2:
            return('h');
        case 3:
            return('s');
    }
}

// Function that changes the rank integer value to a character
// representing the rank

char getRank(int rank)
{
    switch (rank)
    {
        case 0:
            return('A');
        case 1:
            return('2');
        case 2:
            return('3');
        case 3:
            return('4');
        case 4:
            return('5');
        case 5:
            return('6');
        case 6:
            return('7');
        case 7:
            return('8');
        case 8:
            return('9');
        case 9:
            return('T');
        case 10:
            return('J');
        case 11:
            return('Q');
        case 12:
            return('K');
    }
}

// Function to get the users' bet between 1 and 5
int getBet()
{
    int bet;

    do //Will keep running until the user enters 0-5
    {
        printf("How much do you want to bet? (Enter a number ");
        printf("1 to 5, or 0 to quit the game): ");
        scanf(" %d", &bet);

        if (bet >= 1 && bet <= 5)
        {
            return(bet);
        }
        else if (bet == 0)
        {
            exit(1);
        }
        else
        {
            printf("\n\nPlease enter a bet from 1-5 or ");
            printf("0 to quit the game.\n");
        }
    } while (true); // From Jas - Missing a while clause here! I've just guessed it!
} // From Jas - This closing brace was missing!

// Last function revviews the final hand and determines the value of
// the hand.
int analyzeHand(int ranksinHand[], int suitsinHand[])
{
    int num_consec = 0;
    int i, rank, suit;
    bool straight = false; // From Jas - this should be bool NOT int
    bool flush = false; // From Jas - bool NOT int
    bool four = false; // From Jas - bool NOT int
    bool three = false; // From Jas - bool NOT int
    int pairs = 0;

    for (suit = 0; suit < 4; suit++)
        if (suitsinHand[suit] == 5)
            flush = true; // From Jas - there was a typo here. should be flush, not fluush!
    rank = 0;
    while (ranksinHand[rank] == 0)
        rank++;
    for (; rank < 13 && ranksinHand[rank]; rank++)
        num_consec++;
    if (num_consec == 5)
        straight = true;

    for (rank = 0; rank < 13; rank++)
    {
        if (ranksinHand[rank] == 4)
            four = true;
        if (ranksinHand[rank] == 3)
            three = true;
        if (ranksinHand[rank] == 2)
            pairs++;
    }

    if (straight && flush)
       {
        printf("Straight flush\n\n");
        return (20);
    }
    else if (four)
    {
        printf("Four of a kind\n\n");
        return (10);
    }
    else if (three && pairs == 1)
    {
        printf("Full house\n\n");
        return (8);
    }
    else if (flush)
       {
        printf("Flush\n\n");
        return (5);
    } // From Jas - This was an open brace, it needed to be a closed brace
    else if (straight)
    {
        printf("Straight\n\n");
        return (4);
    }
    else if (three)
    {
        printf("Three of a kind\n\n");
        return (3);
    }
    else if (pairs == 2)
    {
        printf("Two pairs\n\n");
        return (2);
    }
    else if (pairs == 1)
       {
        printf("Pair\n\n");
        return (1);
    }
    else
       {
        printf("High Card\n\n");
        return (0);
    }
}

// This function looks through each of the five cards in the first hand
// and asks the user if they want to keep the card. If they say no,
// they get a replacement card.
void getFinalHand(int cardRank[], int cardSuit[], int finalRank[],
        int finalSuit[], int ranksinHand[],
        int suitsinHand[])
{
    int i, j, cardDup;
    char suit, rank, ans;

    for (i=0; i < 5; i++)
    {
        suit = getSuit(cardSuit[i]);
        rank = getRank(cardRank[i]);
        printf("Do you want to keep card #%d: %c%c?", i+1, rank, suit);
        printf("\nPlease answer (Y/N): ");
        scanf(" %c", &ans);
        if (toupper(ans) == 'Y')
        {
            finalRank[i] = cardRank[i];
            finalSuit[i] = cardSuit[i];
            ranksinHand[finalRank[i]]++;
            suitsinHand[finalSuit[i]]++;
            continue;
        }
        else if (toupper(ans) == 'N')
        {
            cardDup = 0;
            do
            {
                cardDup = 0;
                finalRank[i] = (rand() % 13);
                finalSuit[i] = (rand() % 4);

                // First check your new card against the 5 original
                // cards to avoid duplication
                for (j=0; j < 5; j++)
                {
                    if ((finalRank[i] == cardRank[j]) &&
                            (finalSuit[i] == cardSuit[j]))
                    {
                        if ((finalRank[i] == cardRank[j]) &&
                                (finalSuit[i] == cardSuit[j]))
                        {
                            cardDup = 1;
                        }
                    }
                } // From Jas - there was a missing closing brace here!

                // Next, check the new card against any newly drawn
                // cards to avoid duplication
                for (j=0; j < i; j++)
                {
                    if ((finalRank[i] == finalRank[j]) &&
                            (finalSuit[i] == finalSuit[j]))
                    {
                        cardDup = 1;
                    }
                }

            } while (cardDup == 1);
            ranksinHand[finalRank[i]]++;
            suitsinHand[finalSuit[i]]++;
        }
    }
}

Also note - I haven't looked through ALL of the logic in the program, so I don't know if there are any bugs in there, or if there are any other lines that you missed - but syntactically what I've got there all looks OK to me and both versions should at least compile without errors and run.

I hope this helps!
 
Last edited:
As an addendum - when it comes to error messages and warnings from gcc (and other compilers/interpreters) the error messages usually tell you the exact line where an error occurs.

However, sometimes the ACTUAL problem isn't on the line mentioned in the error message. But rather, on the line immediately BEFORE.

So for example, in your original post - where the compiler was complaining:
Code:
Draw_Poker.c: in function getBet():
Draw_Poker.c:269:5 error expeced `while` before `int`:
269 |        int analyzeHand(int ranksinHand[], int suitsinHand[])
    |        ^

I imagine when you first saw that error, the first thing you thought was:
"But that's the start of the definition of my analyzeHand function! Why does it say it expects `while` instead of `int`?! And why does it say that the error is in the getBet function?!"

But in this case, the compiler isn't complaining that line 269 is wrong. It's actually saying that it was expecting a while statement at line 269 - so something went wrong somewhere before that line.

So, as an inexperienced programmer - how do you work out how to solve the problem?
Well, in your original code, what you would have needed to do was look up a few lines at your getBet function:
C:
// Function to get the users' bet between 1 and 5
int getBet()
    {
        int bet;

        do //Will keep running until the user enters 0-5
        {
            printf("How much do you want to bet? (Enter a number ");
            printf("1 to 5, or 0 to quit the game): ");
            scanf(" %d", &bet);

            if (bet >= 1 && bet <= 5)
            {
                return(bet);
            }
            else if (bet == 0)
            {
                exit(1);
            }
            else
            {
                printf("\n\nPlease enter a bet from 1-5 or ");
                printf("0 to quit the game.\n");
            }
    } << Last line of code BEFORE the error

    // Last function revviews the final hand and determines the value of
    // the hand.
    int analyzeHand(int ranksinHand[], int suitsinHand[]) << compiler says this line is wrong!!
    {
        int num_consec = 0;
        int i, rank, suit;
// More code below here
Above is your original code.

So looking at the line before the line being complained about (ignoring any lines with comments) - the last actual line of code was a closing brace - and to you - it looks like the closing brace for your getBet function. How could that possibly be wrong?

Well, the next thing to do is take a look at the entire getBet function.
So start at the beginning of the function, go through everything and ensure that all of the braces match up.
e.g. any opening braces have corresponding closing braces.
And that everything else is syntactically correct.

Also make note of the do loop in your function. It's worth remembering that do loops require a corresponding while condition after the closing brace for the do loop.

So the next step is to trace your way through the braces to find the closing brace for the do loop. And you'll see that the final closing brace for the getBet function is actually the closing brace for the do loop AND that you're also missing a brace to close the function.

So a while condition needs to be added after the closing brace for the do loop AND you need a final closing brace to end the function definition.

And that would fix that particular problem! And then you'd move on to the next error message.

In reality, I imagine that when you typed out the original code, you probably just accidentally missed out the line that contained the closing brace for the do loop and it's corresponding while condition and only entered the closing brace for the function.

In doing that, your braces were mis-matched AND as we've seen the block of code for the do loop was not being terminated correctly.

So when you compiled the code - the compiler reached the closing-brace that YOU thought marked the end of the function definition. When in fact, from the compilers point of view - that brace actually terminated the do loop. And immediately after the do loop, the compiler expects to see a while condition.
Also, because the final closing brace for the function was missing, the very next thing the compiler found was int - which was the return type for your analyzeHand function. Which is why it complained about the int in the line for the analyzeHand function definition AND said it was inside the getBet function.
Which is why it threw that potentially confusing error.

Now, if you imagine that the closing brace for the getBet function was there. AND that the while condition was missing from the do loop -then you would have got exactly the same error message as before. It would complain that the error was in the getBet function, but the line of code it complained about would be the closing brace for the function.
So again - the problem would be on the line immediately before the error - because we're missing the while condition on the previous line, which is the closing brace for the do loop!

I hope that makes sense?!

Interpreting compiler errors and warnings in any programming language can be tricky sometimes, it's not always immediately obvious where the actual error is. But it's a skill that you will improve through experience. You often have to think like a compiler. Think about the rules of the language and why it might be throwing an error in that particular part of the code.

If the location of the error is NOT immediately obvious and you can't see a problem on the line before, then start by taking a look at the top-level item in the error message.

So, in this case, the top-level item was the getBet function.
The compilers error message said that the error was occurring inside the getBet function.
It couldn't possibly be a problem with the definition of your analyzeHand function, as per the line of code it highlighted. Syntactically, that line is correct. So it must be a problem with the getBet function, somewhere at the end.

But as we saw above, the problem was actually the mis-matched braces in the function above it. The do..while didn't have a while AND the function was not closed properly either. So it was actually sort-of two problems, NOT one!
But either way, those problems lead to a compiler error.

Again, accurately interpreting error messages from compilers is a skill that you'll pick up in time.

As an experienced programmer, the error message you posted told me pretty much everything I needed to know.
Seeing that the error message said that the error was inside your getBet function and that the line highlighted by the error message was the start of your analyzeHand function's definition:- That immediately told me, without even looking at the code - that your getBet function had not been terminated properly with a closing brace.
The only remaining problem to solve was why the compiler expected a while statement. The first thing that came to mind was a do loop without a while condition at the end.

The next thing I did:
I copy/pasted all of your code into vim and ran a quick gg=G command to auto-indent/reformat all of the code.
Then I immediately saw that there were some imbalances in the braces and balanced them out myself.

And sure enough getBet, was NOT terminated correctly. So I fixed that. And immediately saw that there was an unterminated do loop. Confirming my suspicions why the compiler was complaing about a missing while
Problem solved!
After that, I had a quick scan-through the rest of the file and identified the other minor problems in the code.

But again, I'm an experienced progammer. I've been doing this for years. When you're starting out- it's a different story.
So I've shared how I would go about solving the problems, if I was in your shoes and unsure why an error was occurring.
And I also shared how I ACTUALLY solved the problem you had, as an experienced progammer.

Hopefully, my explanations all made sense. But if you have any questions, fire away!
 
Last edited:
As an addendum - when it comes to error messages and warnings from gcc (and other compilers/interpreters) the error messages usually tell you the exact line where an error occurs.

However, sometimes the ACTUAL problem isn't on the line mentioned in the error message. But rather, on the line immediately BEFORE.

So for example, in your original post - where the compiler was complaining:
Code:
Draw_Poker.c: in function getBet():
Draw_Poker.c:269:5 error expeced `while` before `int`:
269 |        int analyzeHand(int ranksinHand[], int suitsinHand[])
    |        ^

I imagine when you first saw that error, the first thing you thought was:
"But that's the start of the definition of my analyzeHand function! Why does it say it expects `while` instead of `int`?! And why does it say that the error is in the getBet function?!"

But in this case, the compiler isn't complaining that line 269 is wrong. It's actually saying that it was expecting a while statement at line 269 - so something went wrong somewhere before that line.

So, as an inexperienced programmer - how do you work out how to solve the problem?
Well, in your original code, what you would have needed to do was look up a few lines at your getBet function:
C:
// Function to get the users' bet between 1 and 5
int getBet()
    {
        int bet;

        do //Will keep running until the user enters 0-5
        {
            printf("How much do you want to bet? (Enter a number ");
            printf("1 to 5, or 0 to quit the game): ");
            scanf(" %d", &bet);

            if (bet >= 1 && bet <= 5)
            {
                return(bet);
            }
            else if (bet == 0)
            {
                exit(1);
            }
            else
            {
                printf("\n\nPlease enter a bet from 1-5 or ");
                printf("0 to quit the game.\n");
            }
    } << Last line of code BEFORE the error

    // Last function revviews the final hand and determines the value of
    // the hand.
    int analyzeHand(int ranksinHand[], int suitsinHand[]) << compiler says this line is wrong!!
    {
        int num_consec = 0;
        int i, rank, suit;
// More code below here
Above is your original code.

So looking at the line before the line being complained about (ignoring any lines with comments) - the last actual line of code was a closing brace - and to you - it looks like the closing brace for your getBet function. How could that possibly be wrong?

Well, the next thing to do is take a look at the entire getBet function.
So start at the beginning of the function, go through everything and ensure that all of the braces match up.
e.g. any opening braces have corresponding closing braces.
And that everything else is syntactically correct.

Also make note of the do loop in your function. It's worth remembering that do loops require a corresponding while condition after the closing brace for the do loop.

So the next step is to trace your way through the braces to find the closing brace for the do loop. And you'll see that the final closing brace for the getBet function is actually the closing brace for the do loop AND that you're also missing a brace to close the function.

So a while condition needs to be added after the closing brace for the do loop AND you need a final closing brace to end the function definition.

And that would fix that particular problem! And then you'd move on to the next error message.

In reality, I imagine that when you typed out the original code, you probably just accidentally missed out the line that contained the closing brace for the do loop and it's corresponding while condition and only entered the closing brace for the function.

In doing that, your braces were mis-matched AND as we've seen the block of code for the do loop was not being terminated correctly.

So when you compiled the code - the compiler reached the closing-brace that YOU thought marked the end of the function definition. When in fact, from the compilers point of view - that brace actually terminated the do loop. And immediately after the do loop, the compiler expects to see a while condition.
Also, because the final closing brace for the function was missing, the very next thing the compiler found was int - which was the return type for your analyzeHand function. Which is why it complained about the int in the line for the analyzeHand function definition AND said it was inside the getBet function.
Which is why it threw that potentially confusing error.

Now, if you imagine that the closing brace for the getBet function was there. AND that the while condition was missing from the do loop -then you would have got exactly the same error message as before. It would complain that the error was in the getBet function, but the line of code it complained about would be the closing brace for the function.
So again - the problem would be on the line immediately before the error - because we're missing the while condition on the previous line, which is the closing brace for the do loop!

I hope that makes sense?!

Interpreting compiler errors and warnings in any programming language can be tricky sometimes, it's not always immediately obvious where the actual error is. But it's a skill that you will improve through experience. You often have to think like a compiler. Think about the rules of the language and why it might be throwing an error in that particular part of the code.

If the location of the error is NOT immediately obvious and you can't see a problem on the line before, then start by taking a look at the top-level item in the error message.

So, in this case, the top-level item was the getBet function.
The compilers error message said that the error was occurring inside the getBet function.
It couldn't possibly be a problem with the definition of your analyzeHand function, as per the line of code it highlighted. Syntactically, that line is correct. So it must be a problem with the getBet function, somewhere at the end.

But as we saw above, the problem was actually the mis-matched braces in the function above it. The do..while didn't have a while AND the function was not closed properly either. So it was actually sort-of two problems, NOT one!
But either way, those problems lead to a compiler error.

Again, accurately interpreting error messages from compilers is a skill that you'll pick up in time.

As an experienced programmer, the error message you posted told me pretty much everything I needed to know.
Seeing that the error message said that the error was inside your getBet function and that the line highlighted by the error message was the start of your analyzeHand function's definition:- That immediately told me, without even looking at the code - that your getBet function had not been terminated properly with a closing brace.
The only remaining problem to solve was why the compiler expected a while statement. The first thing that came to mind was a do loop without a while condition at the end.

The next thing I did:
I copy/pasted all of your code into vim and ran a quick gg=G command to auto-indent/reformat all of the code.
Then I immediately saw that there were some imbalances in the braces and balanced them out myself.

And sure enough getBet, was NOT terminated correctly. So I fixed that. And immediately saw that there was an unterminated do loop. Confirming my suspicions why the compiler was complaing about a missing while
Problem solved!
After that, I had a quick scan-through the rest of the file and identified the other minor problems in the code.

But again, I'm an experienced progammer. I've been doing this for years. When you're starting out- it's a different story.
So I've shared how I would go about solving the problems, if I was in your shoes and unsure why an error was occurring.
And I also shared how I ACTUALLY solved the problem you had, as an experienced progammer.

Hopefully, my explanations all made sense. But if you have any questions, fire away!
@JasKinasis
Jason,
Got through pretty much the whole thing with improvements and education along the way.
Now I only got one small error message.
I actually counted all the curly braces in analyzeHand on down and then added one ending brace at the end, as it was one brace short.
After I did that and went to re-compile it, the second message came up. That has quite a few new things in it. What does ld mean? Also, I looked at the 'getFinalHand' but can't figure out what that is telling me. Again, many thanks for sharing your expertise in this area. Man, this is really a lot of work, and a lot of fun. OC Charlie
I really do like the braces on separate lines.


error_first_the_undefined_ref.png


Here's the present file:

Code:
// Example poker program from Appendix B of Absolute Beginner's
// Guide to C, 3rd Edition
// File AppendixBpoker.c

    /* This program plays draw poker. Users can play as often as they
want, betting between 1 and 5. They are dealt 5 cards and then get
to choose which cards to keep, and which cards to replace. The new
hand is then reviewed and the user's payout is set based on the
value of the hand. The user's new bankroll is displayed as they are
given the option to continue. */

    // Header files

#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <stdlib.h>

// Two constants defined for determining whether hands are flushes
// or straights

#define FALSE 0
#define TRUE 1

// Function prototyping

void printGreeting();
int getBet();
char getSuit(int suit);
char getRank(int rank);

void getFirstHand(int cardRank[], int cardSuit[]);
void getFinalHand(int cardRank[], int cardSuit[], int finalRank[],
            int finalSuit[], int ranksinHand[],
            int suitsinHand[]);
int analyzeHand(int ranksinHand[], int suitsinHand[]);


int main()

{
    int bet;
    int bank = 100;
    int i;
    int cardRank[5]; //Will be one of 13 values (Ace-King)
    int cardSuit[5]; //Will be one of 4 values (for Clubs, Diamonds,
                        // Hearts, Spades)

    int finalRank[5];
    int finalSuit[5];

    int ranksinHand[13];  //Used for evaluating the final hand
    int suitsinHand[4];   //Used for evaluating the final hand

    int winnings;
    time_t t;
    char suit, rank, stillPlay;

    //This function is called outside the do...while loop because
    //the greeting
    //only needs to be displayed once, while everything else in main
    //will run
    //multiple times, depending on how many times the user wants to
    //play.

    printGreeting();
                    //Loop runs each time the user plays a hand of draw poker

    do
    {
        bet = getBet();

        srand(time(&t));
        getFirstHand(cardRank, cardSuit);

        printf("Your five cards: \n");
        for (i = 0; i <5; i++)

       {
            suit = getSuit(cardSuit[i]);
            rank = getRank(cardRank[i]);
            printf("Card #%d: %c%c\n", i+1, rank, suit);
       }

        // These two arrays are used to figure out the value of
        // the players' hand. However, they must be zeroed out
        // in case the user plays multiple hands.

    for (i=0; i < 13; i++)
        {
      ranksinHand[i] = 0;
        }


    getFinalHand(cardRank, cardSuit, finalRank, finalSuit,
                            ranksinHand, suitsinHand);

    printf("Your five final cards: \n");
    for (i = 0; i < 5; i++)

        {
      suit = getSuit(finalSuit[i]);
      rank = getRank(finalRank[i]);
      printf("Card #%d: %c%c\n", i+1, rank, suit);
        }

        winnings = analyzeHand(ranksinHand, suitsinHand);
        printf("You won %d!\n", bet*winnings);
        bank = bank - bet + (bet*winnings);
        printf("\nYour bank is now %d.\n", bank);
        printf("\nDo you want to play again? ");
        scanf(" %c", &stillPlay);

    } while (toupper(stillPlay) == 'Y');

    return 0;
}

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

    // Print a quick greeting as well as tell the users the value of
    // different winning hands

    void printGreeting()
    {
        printf("*****************************************************\n");
        printf("\n\n\tWelcome to the Absolute Beginners' Casino\n\n");
        printf("\tHome of Video Draw Poker\n\n");
        printf("*****************************************************\n");

        printf("Here are the rules:\n");
        printf("You start with 100 credits, and you make a bet from ");
        printf("1 to 5 credits.\n");
        printf("You are dealt 5 cards, and you then choose which ");
        printf("cards to keep ");
        printf("or discard.\n");
        printf("You want to make the best possible hand.\n");
        printf("\nHere is the table for winnings (assuming a ");
        printf("bet of 1 credit):");
        printf("\nPair\t\t\t\t1 credit");
        printf("\nTwo pairs\t\t\t2 credits");
        printf("\nThree of a kind\t\t\t3 credits");
        printf("\nStraight\t\t\t4 credits");
        printf("\nFlush\t\t\t\t5 credits");
        printf("\nFull House\t\t\t8 credits");
        printf("\nFour of a Kind\t\t\t10 credits");
        printf("\nStraight Flush\t\t\t20 credits");
        printf("\n\nHave fun!!\n\n");
    }


// Function to deal the first five cards

    void getFirstHand(int cardRank[], int cardSuit[])

    {
        int i,j;
        int cardDup;

        for (i=0; i < 5; i++)
        {

                cardDup = 0;
                do {
                    // Card rank is one of 13 (2-10, J, Q, K, A)
                    cardRank[i] = (rand() % 13);
                    // Card suit is one of 4
                    // (club, diamond, heart, spade)
                    cardSuit[i] = (rand() % 4);

                    // Loop that ensures each card is unique
                    for (j=0; j < i; j++)
                    {
              if ((cardRank[i] == cardRank[j]) &&
              (cardSuit[i]))
              {
            cardDup = 1;
                      }

                }
        } while (cardDup == 1);
    }
}

// Function that changes the suit integer value to a character
// representing the suit

 char getSuit(int suit)
 {
      switch (suit)
      {

            case 0:
                return('c');
            case 1:
                return('d');
            case 2:
                return('h');
            case 3:
                return('s');
      }
 }

// Function that changes the rank integer value to a character
// representing the rank

char getRank(int rank)
{
  switch (rank)
  {
         case 0:
             return('A');
         case 1:
             return('2');
         case 2:
             return('3');
         case 3:
             return('4');
         case 4:
             return('5');
         case 5:
             return('6');
         case 6:
             return('7');
         case 7:
             return('8');
         case 8:
             return('9');
         case 9:
             return('T');
         case 10:
             return('J');
         case 11:
             return('Q');
         case 12:
             return('K');
    }
 }

// Function to get the users' bet between 1 and 5

int getBet()
{
     int bet;

     do //Will keep running until the user enters 0-5
     {
         printf("How much do you want to bet? (Enter a number ");
         printf("1 to 5, or 0 to quit the game): ");
         scanf(" %d", &bet);

         if (bet >= 1 && bet <= 5)
         {
             return(bet);
         }
         else if (bet == 0)
         {
             exit(1);
         }
         else
         {
             printf("\n\nPlease enter a bet from 1-5 or ");
             printf("0 to quit the game.\n");
         }
     } while (TRUE);
}

    // Last function revviews the final hand and determines the value of
    // the hand.

    int analyzeHand(int ranksinHand[], int suitsinHand[])
{
        int num_consec = 0;
        int i, rank, suit;
        int straight = FALSE;
        int flush = FALSE;
        int four = FALSE;
        int three = FALSE;
        int pairs = 0;

        for (suit = 0; suit < 4; suit++)
            if (suitsinHand[suit] == 5)
                flush = TRUE;
        rank = 0;
        while (ranksinHand[rank] == 0)
            rank++;
        for (; rank < 13 && ranksinHand[rank]; rank++)
            num_consec++;
        if (num_consec == 5)   
{
            straight = TRUE;
        
        for (rank = 0; rank < 13; rank++)
{
            if (ranksinHand[rank] == 4)
                four = TRUE;
            if (ranksinHand[rank] == 3)
                three = TRUE;
            if (ranksinHand[rank] == 2)
                pairs++;
   }

        if (straight && flush)
{
            printf("Straight flush\n\n");
            return (20);
   }
        else if (four)
{
            printf("Four of a kind\n\n");
            return (10);
   }
        else if (three && pairs == 1)
{
            printf("Full house\n\n");
            return (8);
   }
        else if (flush)
{
            printf("Flush\n\n");
            return (5);
   }
        else if (straight)
{
            printf("Straight\n\n");
            return (4);
   }
        else if (three)
{
            printf("Three of a kind\n\n");
            return (3);
   }
        else if (pairs == 2)
{
            printf("Two pairs\n\n");
            return (2);
   }
        else if (pairs == 1)
{
            printf("Pair\n\n");
            return (1);
   }
        else
{
          printf("High Card\n\n");
            return (0);
   }
     }

    // This function looks through each of the five cards in the first hand
    // and asks the user if they want to keep the card. If they say no,
    // they get a replacement card.

    void getFinalHand(int cardRank[], int cardSuit[], int finalRank[],
            int finalSuit[], int ranksinHand[],
            int suitsinHand[])
{
      int i, j, cardDup;
      char suit, rank, ans;

      for (i=0; i < 5; i++)
{
         suit = getSuit(cardSuit[i]);
         rank = getRank(cardRank[i]);
         printf("Do you want to keep card #%d: %c%c?", i+1, rank, suit);
         printf("\nPlease answer (Y/N): ");
         scanf(" %c", &ans);
         if (toupper(ans) == 'Y')
{
            finalRank[i] = cardRank[i];
            finalSuit[i] = cardSuit[i];
            ranksinHand[finalRank[i]]++;
            suitsinHand[finalSuit[i]]++;
            continue;
    }
         else if (toupper(ans) == 'N')
{
            cardDup = 0;
            do
{
                cardDup = 0;
                finalRank[i] = (rand() % 13);
                finalSuit[i] = (rand() % 4);

        // First check your new card against the 5 original
        // cards to avoid duplication
        for (j=0; j < 5; j++)
{
          if ((finalRank[i] == cardRank[j]) &&
              (finalSuit[i] == cardSuit[j]))
{
          if ((finalRank[i] == cardRank[j]) &&
              (finalSuit[i] == cardSuit[j]))
{
              cardDup = 1;
             }
           }
         }

        // Next, check the new card against any newly drawn
        // cards to avoid duplication
        for (j=0; j < i; j++)
{
          if ((finalRank[i] == finalRank[j]) &&
                      (finalSuit[i] == finalSuit[j]))
{
            cardDup = 1;
    }
    }

               } while (cardDup == 1);
               ranksinHand[finalRank[i]]++;
               suitsinHand[finalSuit[i]]++;
    }
    }
    }
    }
 
You've got:


Code:
  } while (toupper(stillPlay) == 'Y');


    return 0;

}

At the bottom of main() (and elsewhere in your code). I think the 'while' needs a closing '}'

keith
 
You've got:


Code:
  } while (toupper(stillPlay) == 'Y');


    return 0;

}

At the bottom of main() (and elsewhere in your code). I think the 'while' needs a closing '}'

keith
Not quite @khedger. That while is the termination condition for the do loop above it. It doesn't need a closing brace.

@70 Tango Charlie
I can see the exact problem, but before I say what it is, I'll just post your code again, but with the correct formatting and indentation and then hopefully the problems will become more obvious for all to see!

But even before that - to explain what I mean by indentation problems, here's a snippet where the indentation in your code looks very confusing:
C:
        else if (pairs == 1)
{
            printf("Pair\n\n");
            return (1);
   }
        else
{
          printf("High Card\n\n");
            return (0);
   }
     }
That's quite gnarly!
And there are a few other places where the indentation of the braces is a bit iffy!

So here's your code again, but with more consistent indentation applied:
C:
// Example poker program from Appendix B of Absolute Beginner's
// Guide to C, 3rd Edition
// File AppendixBpoker.c

/* This program plays draw poker. Users can play as often as they
   want, betting between 1 and 5. They are dealt 5 cards and then get
   to choose which cards to keep, and which cards to replace. The new
   hand is then reviewed and the user's payout is set based on the
   value of the hand. The user's new bankroll is displayed as they are
   given the option to continue. */

// Header files

#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <stdlib.h>

// Two constants defined for determining whether hands are flushes
// or straights

#define FALSE 0
#define TRUE 1

// Function prototyping

void printGreeting();
int getBet();
char getSuit(int suit);
char getRank(int rank);

void getFirstHand(int cardRank[], int cardSuit[]);
void getFinalHand(int cardRank[], int cardSuit[], int finalRank[],
        int finalSuit[], int ranksinHand[],
        int suitsinHand[]);
int analyzeHand(int ranksinHand[], int suitsinHand[]);


int main()

{
    int bet;
    int bank = 100;
    int i;
    int cardRank[5]; //Will be one of 13 values (Ace-King)
    int cardSuit[5]; //Will be one of 4 values (for Clubs, Diamonds,
    // Hearts, Spades)

    int finalRank[5];
    int finalSuit[5];

    int ranksinHand[13];  //Used for evaluating the final hand
    int suitsinHand[4];   //Used for evaluating the final hand

    int winnings;
    time_t t;
    char suit, rank, stillPlay;

    //This function is called outside the do...while loop because
    //the greeting
    //only needs to be displayed once, while everything else in main
    //will run
    //multiple times, depending on how many times the user wants to
    //play.

    printGreeting();
    //Loop runs each time the user plays a hand of draw poker

    do
    {
        bet = getBet();

        srand(time(&t));
        getFirstHand(cardRank, cardSuit);

        printf("Your five cards: \n");
        for (i = 0; i <5; i++)

        {
            suit = getSuit(cardSuit[i]);
            rank = getRank(cardRank[i]);
            printf("Card #%d: %c%c\n", i+1, rank, suit);
        }

        // These two arrays are used to figure out the value of
        // the players' hand. However, they must be zeroed out
        // in case the user plays multiple hands.

        for (i=0; i < 13; i++)
        {
            ranksinHand[i] = 0;
        }


        getFinalHand(cardRank, cardSuit, finalRank, finalSuit,
                ranksinHand, suitsinHand);

        printf("Your five final cards: \n");
        for (i = 0; i < 5; i++)

        {
            suit = getSuit(finalSuit[i]);
            rank = getRank(finalRank[i]);
            printf("Card #%d: %c%c\n", i+1, rank, suit);
        }

        winnings = analyzeHand(ranksinHand, suitsinHand);
        printf("You won %d!\n", bet*winnings);
        bank = bank - bet + (bet*winnings);
        printf("\nYour bank is now %d.\n", bank);
        printf("\nDo you want to play again? ");
        scanf(" %c", &stillPlay);

    } while (toupper(stillPlay) == 'Y');

    return 0;
}

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

// Print a quick greeting as well as tell the users the value of
// different winning hands

void printGreeting()
{
    printf("*****************************************************\n");
    printf("\n\n\tWelcome to the Absolute Beginners' Casino\n\n");
    printf("\tHome of Video Draw Poker\n\n");
    printf("*****************************************************\n");

    printf("Here are the rules:\n");
    printf("You start with 100 credits, and you make a bet from ");
    printf("1 to 5 credits.\n");
    printf("You are dealt 5 cards, and you then choose which ");
    printf("cards to keep ");
    printf("or discard.\n");
    printf("You want to make the best possible hand.\n");
    printf("\nHere is the table for winnings (assuming a ");
    printf("bet of 1 credit):");
    printf("\nPair\t\t\t\t1 credit");
    printf("\nTwo pairs\t\t\t2 credits");
    printf("\nThree of a kind\t\t\t3 credits");
    printf("\nStraight\t\t\t4 credits");
    printf("\nFlush\t\t\t\t5 credits");
    printf("\nFull House\t\t\t8 credits");
    printf("\nFour of a Kind\t\t\t10 credits");
    printf("\nStraight Flush\t\t\t20 credits");
    printf("\n\nHave fun!!\n\n");
}


// Function to deal the first five cards

void getFirstHand(int cardRank[], int cardSuit[])

{
    int i,j;
    int cardDup;

    for (i=0; i < 5; i++)
    {

        cardDup = 0;
        do {
            // Card rank is one of 13 (2-10, J, Q, K, A)
            cardRank[i] = (rand() % 13);
            // Card suit is one of 4
            // (club, diamond, heart, spade)
            cardSuit[i] = (rand() % 4);

            // Loop that ensures each card is unique
            for (j=0; j < i; j++)
            {
                if ((cardRank[i] == cardRank[j]) &&
                        (cardSuit[i]))
                {
                    cardDup = 1;
                }

            }
        } while (cardDup == 1);
    }
}

// Function that changes the suit integer value to a character
// representing the suit

char getSuit(int suit)
{
    switch (suit)
    {

        case 0:
            return('c');
        case 1:
            return('d');
        case 2:
            return('h');
        case 3:
            return('s');
    }
}

// Function that changes the rank integer value to a character
// representing the rank

char getRank(int rank)
{
    switch (rank)
    {
        case 0:
            return('A');
        case 1:
            return('2');
        case 2:
            return('3');
        case 3:
            return('4');
        case 4:
            return('5');
        case 5:
            return('6');
        case 6:
            return('7');
        case 7:
            return('8');
        case 8:
            return('9');
        case 9:
            return('T');
        case 10:
            return('J');
        case 11:
            return('Q');
        case 12:
            return('K');
    }
}

// Function to get the users' bet between 1 and 5

int getBet()
{
    int bet;

    do //Will keep running until the user enters 0-5
    {
        printf("How much do you want to bet? (Enter a number ");
        printf("1 to 5, or 0 to quit the game): ");
        scanf(" %d", &bet);

        if (bet >= 1 && bet <= 5)
        {
            return(bet);
        }
        else if (bet == 0)
        {
            exit(1);
        }
        else
        {
            printf("\n\nPlease enter a bet from 1-5 or ");
            printf("0 to quit the game.\n");
        }
    } while (TRUE);
}

// Last function revviews the final hand and determines the value of
// the hand.

int analyzeHand(int ranksinHand[], int suitsinHand[])
{
    int num_consec = 0;
    int i, rank, suit;
    int straight = FALSE;
    int flush = FALSE;
    int four = FALSE;
    int three = FALSE;
    int pairs = 0;

    for (suit = 0; suit < 4; suit++)
        if (suitsinHand[suit] == 5)
            flush = TRUE;
    rank = 0;
    while (ranksinHand[rank] == 0)
        rank++;
    for (; rank < 13 && ranksinHand[rank]; rank++)
        num_consec++;
    if (num_consec == 5) 
    {
        straight = TRUE;

        for (rank = 0; rank < 13; rank++)
        {
            if (ranksinHand[rank] == 4)
                four = TRUE;
            if (ranksinHand[rank] == 3)
                three = TRUE;
            if (ranksinHand[rank] == 2)
                pairs++;
        }

        if (straight && flush)
        {
            printf("Straight flush\n\n");
            return (20);
        }
        else if (four)
        {
            printf("Four of a kind\n\n");
            return (10);
        }
        else if (three && pairs == 1)
        {
            printf("Full house\n\n");
            return (8);
        }
        else if (flush)
        {
            printf("Flush\n\n");
            return (5);
        }
        else if (straight)
        {
            printf("Straight\n\n");
            return (4);
        }
        else if (three)
        {
            printf("Three of a kind\n\n");
            return (3);
        }
        else if (pairs == 2)
        {
            printf("Two pairs\n\n");
            return (2);
        }
        else if (pairs == 1)
        {
            printf("Pair\n\n");
            return (1);
        }
        else
        {
            printf("High Card\n\n");
            return (0);
        }
    }

// This function looks through each of the five cards in the first hand
// and asks the user if they want to keep the card. If they say no,
// they get a replacement card.

void getFinalHand(int cardRank[], int cardSuit[], int finalRank[],
        int finalSuit[], int ranksinHand[],
        int suitsinHand[])
{
    int i, j, cardDup;
    char suit, rank, ans;

    for (i=0; i < 5; i++)
    {
        suit = getSuit(cardSuit[i]);
        rank = getRank(cardRank[i]);
        printf("Do you want to keep card #%d: %c%c?", i+1, rank, suit);
        printf("\nPlease answer (Y/N): ");
        scanf(" %c", &ans);
        if (toupper(ans) == 'Y')
        {
            finalRank[i] = cardRank[i];
            finalSuit[i] = cardSuit[i];
            ranksinHand[finalRank[i]]++;
            suitsinHand[finalSuit[i]]++;
            continue;
        }
        else if (toupper(ans) == 'N')
        {
            cardDup = 0;
            do
            {
                cardDup = 0;
                finalRank[i] = (rand() % 13);
                finalSuit[i] = (rand() % 4);

                // First check your new card against the 5 original
                // cards to avoid duplication
                for (j=0; j < 5; j++)
                {
                    if ((finalRank[i] == cardRank[j]) &&
                            (finalSuit[i] == cardSuit[j]))
                    {
                        if ((finalRank[i] == cardRank[j]) &&
                                (finalSuit[i] == cardSuit[j]))
                        {
                            cardDup = 1;
                        }
                    }
                }

                // Next, check the new card against any newly drawn
                // cards to avoid duplication
                for (j=0; j < i; j++)
                {
                    if ((finalRank[i] == finalRank[j]) &&
                            (finalSuit[i] == finalSuit[j]))
                    {
                        cardDup = 1;
                    }
                }

            } while (cardDup == 1);
            ranksinHand[finalRank[i]]++;
            suitsinHand[finalSuit[i]]++;
        }
    }
}
}

What can we see in the above? Can anybody see it now?!
It's only two minor mistakes/typos.....

No?!
OK, let's take a look at the error that Charlie posted.
The error states that the problem is in the analyzeHand function, so let's look there.

If you look at the start of the analyzeHand function - everything looks OK.
But work your way down to the bottom of the function and you'll see that its closing brace is missing.
Add a closing brace at the bottom of that function, before the comments for the next function and that's that problem fixed!

But, don't celebrate just yet! There's a second little goof.
At the very bottom of the code. There is an extra closing brace at the end of the file too! So that extra, final brace needs to be removed too!

And then the code will finally compile with no errors.

Regarding the indentation of the braces:-
Perhaps I wasn't entirely clear on the subject in my other post. I forgot to mention that the braces should always be indented so that:
1. The opening braces always line up with the first non-whitespace character of the statement above them.
And
2. Their corresponding closing brace should be indented to exactly the same level as the opening brace.
e.g.
C:
void aFunction()
{
        if(something)
        {
               callAFunction();
               doOtherThing();
        } // end if
        else
        {
               doSomethingDifferent();
        } // end else
} // end function

In the above, I've added a comment after each closing brace, so you can see which brace is for what.
Also - each opening brace is lined up with the first non-whitespace character of the statement above it.
Likewise - each closing brace is in line with it's corresponding opening brace.

To highlight the importance of good, consistent indentation -
Consider this function. It's just something nonsensical that I've made up.

What follows has no indentation whatsoever.
Now, is this valid code or not? What do you think?
C:
int someFunction(int y)
{
int x=0;
if (y<25)
{
for(x=0;x<25;++x)
{
y += callAnotherFunction(x);
if (y > LIMIT)
{
y = LIMIT;
}
}
}
return y;
}
It looks awful doesn't it?!
You can't easily tell where blocks of code start and end?

Would this code compile? (assuming it was in a complete program and not just a tiny snippet!)

In actual fact, a compiler would happily accept that code. Syntactically it's absolutely fine. However, because of the lack of indentation, it's not very readable for us humans. So we'd have a difficult time working out what it does.

Now let's look at that same code again, but with sensible and consistent indentation:
C:
int someFunction(int y)
{
        int x=0;
        if (y<25)
        {
                for(x=0;x<25;++x)
                {
                        y += callAnotherFunction(x);
                        if (y > LIMIT)
                        {
                             y = LIMIT;
                        }
                }
        }
        return y;
}

Now you can see where each logical block of code starts and ends. It's extremely readable.

So, correct indentation of code AND indentation of braces is extremely important, in order to be able to spot problems in your code.

Also, going back to the example where I put comments on each end-brace:
As a beginner - commenting your closing braces like this is another tactic you can employ to ensure that your braces are matched up correctly.

For example:
When you're working on a large, complex function with multiple levels of indentation. At the end of the function, you might end up with a ton of lines containing cascading closing braces like this:
C:
                        }
               }
        }
}
Now, how do you know which blocks of code each of those braces are closing off?
You could scroll up through the code to see which opening brace lines up with the closing brace. But in an extremely complex piece of code, it might mean having to scroll up a couple of hundred lines of code.
So another way to be absolutely sure - would be to comment the closing braces.
e.g.
C:
                        } // end if
               } // end secondary loop
        } // end main loop
}  // end myFunction
Above isn't a concrete example, it's just an arbitrary, abstract example, so you just have to imagine that there's a ton of complicated code above all of those closing braces!

I've done this kind of thing in the past and it can be useful to do sometimes.

for example - if you suddenly discovered a bug which meant that you needed to call a function AFTER your secondary loop has finished, but before the main loop re-iterates - you can see which block of code is being closed by each brace and you know exactly where to insert your function call:
e.g.
C:
                        } // end if
               } // end secondary loop
               callSomeFunction(); // << function call goes here to fix the bug!
        } // end main loop
}  // end myFunction
Now we've fixed the bug we found!

So that's another tip for beginner C programmers. If your code is getting complicated - Label your closing braces with comments.
Typically, it's not the sort of thing you'd see in production code. But as a diagnostic tool for beginner programmers, it's great!
 
@JasKinasis
Man oh man, I am going to owe you a whole brewery pretty soon!!!
Thank you, thank you, ever so much.
I see your point with the braces, both lining them up right and commenting them. What a difference in the looks and easy readability.
I'm not ready to sell the training wheels yet...... but, maybe in the near future!!!
Now I just have to make some changes and see how it goes.
Renewed Geezer, LOL. TC
 
@JasKinasis @khedger
Hey guys,
Thanks a bunch. I finally got it to compile after many tries. Hopefully I have learned a bunch on this poker program.
Now if I could remember how to mark this as 'SOLVED' I would do it.
Thanks again for your help.
OG TC :)
 
Now if I could remember how to mark this as 'SOLVED' I would do it.
Jump up to the title at the top. I don't remember the exact steps, but you can edit the title of any thread that you create, so just add [SOLVED] at the beginning (but leave the rest intact). :)
 
Jump up to the title at the top. I don't remember the exact steps, but you can edit the title of any thread that you create, so just add [SOLVED] at the beginning (but leave the rest intact). :)
Thanks Stan.
TC
 

Members online


Latest posts

Top