指向指针的指针以避免重复代码?

Pointers to Pointers to Avoid Duplicate Code?

我刚开始学习 C,所以作为练习,我尝试创建一个基于文本的纸牌游戏,其中每个 person/CPU 在他们的牌组顶部放置一张 运行dom 牌,拥有更高牌的人将拿走该牌并将其添加到他们的牌组中。在平局期间,两张牌都会被弃掉。当一个人的牌数为零时,在这场比赛中他们就输了。它基本上是 war 纸牌游戏的简化版本。

刚开始开发不久就遇到了一个问题。这是我 运行 遇到错误之前的代码:

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

enum suit {
    heart = 0,
    spade = 1,
    club = 2,
    diamond = 3
};

struct card {
    enum suit current_card_suit;
    int card_num;
    int is_red_card;
};

int cardDeckSize = 0;

int numOpponentCardsLeft;
int numPlayerCardsLeft;

void deal_cards_to_player (struct card * pPlayerCards, int cardDeckSize);
void deal_cards_to_cpu (struct card * pCpuCards, int cardDeckSize);

int get_random_number_above_zero(int max);
void waitFor(unsigned int seconds);

void flush_input() {
    int ch;
    while ((ch = getchar()) != '\n' && ch != EOF)
    continue;
}

int main (int argc, char **argv) {
    //Get Random number sequence for later
    srand(time(NULL));

    int random_suit;
    char userInput[10];
    //Get deck size for war game
    int invalidSize = 1;

    while (invalidSize == 1) {
        printf("\nEnter the amount of cards you would like to be dealed to each player for the war game (between 0 and 100)\n");

        fgets(userInput, 9, stdin);

        if(sscanf(userInput, "%i", &cardDeckSize) != 1) {
            printf("\nPlease enter an integer. You will have to enter the number twice because you did not follow directions.\n");
            flush_input();
            continue;
        }
        if(cardDeckSize > 0 && cardDeckSize < 101) {
            invalidSize = 0;
            break;
        } else {
            printf("\nPlease type a number between 0 and 100. You will have to enter the number twice because you did not follow directions.\n");
            flush_input();
            continue;
        }
    }
    printf("\nPress enter once more to proceed...");
    flush_input();

    //Create arrays to hold the cards of the player and CPU
    struct card *pPlayerCards;
    struct card *pCpuCards;

    pPlayerCards = (struct card *) malloc (cardDeckSize * sizeof(struct card));
    pCpuCards = (struct card *) malloc (cardDeckSize * sizeof(struct card));

    //You will see duplication in the two functions called below, but I could not figure out how to remove it; it works for now
    deal_cards_to_player(pPlayerCards, cardDeckSize);
    deal_cards_to_cpu(pCpuCards, cardDeckSize);

    printf("\nWow! My hand is SO tired of dealing all those cards.  Let's play!\n\n");

    struct card **pCurrentSideCards;
    //"parse" the properties of each card...and right after show the game round results to the player
    /* I will have to change "i < cardDeckSize" eventually becuase the size of the deck will not necessarily determine
     the # of rounds; I'll get through one round first before worrying about this */
    for(int i = 0; i < cardDeckSize; i++) { //Loop through each round

        //Countdown for the player
        printf("3, ");
        waitFor(1);
        printf("2, ");
        waitFor(1);
        printf("1, ");
        waitFor(1);
        printf("GO, GO, GO!!!");
        waitFor(1);

        char playerCardSuit[6];
        char cpuCardSuit[6];

        char playerStringCardNum[5];
        char cpuStringCardNum[5];

        char playerCardColor[5];
        char cpuCardColor[5];

        //Determine card terms set for each player
        for (int i = 0; i < 2; i++) {
            /* To eliminate duplication, based on the current iteration I tried to
            create a pointer that points to a pointer to the array of card structures
            for each player */
            if(i == 0) {
                //Start with "parsing" the player cards, then the CPU cards
                pCurrentSideCards = &pPlayerCards;
            } else {
                pCurrentSideCards = &pCpuCards;
            }

            char cardSuit[6];

            //EXPLANATION:
            /* Accessing the card properties: I first tried to dereference the pointer
            to find a pointer to the card deck structure array.  Then I accessed
            the correct card member in the array with "+i".  I finally tried
            to access the value with the "->" symbol, which dereferences again
 before accessing the member
            */
            switch ( ((*pCurrentSideCards)+i)->current_card_suit) {
                case heart:
                strcpy(cardSuit, "hearts");
                break;
                case spade:
                strcpy(cardSuit, "spades");
                break;
                case club:
                strcpy(cardSuit, "clubs");
                break;
                case diamond:
                strcpy(cardSuit, "diamonds");
                break;
                default:
                printf("\nThere was a fatal error determining the card suit of some dealt out cards.\n");
            }
            if(i == 0) { //If i = 0 we are working with the player cards, otherwise we are working with the CPU cards
                strcpy(playerCardSuit, cardSuit);
            } else {
                strcpy(cpuCardSuit, cardSuit);
            }

            char stringCardNum[5];


            switch ( ((*pCurrentSideCards)+i) ->card_num) {
                case 1:
                strcpy(stringCardNum, "ace");
                break;
                case 11:
                strcpy(stringCardNum, "jack");
                break;
                case 12:
                strcpy(stringCardNum, "queen");
                break;
                case 13:
                strcpy(stringCardNum, "king");
                break;

                default: {
                    int cardAsNumber = ((*pCurrentSideCards)+i) -> card_num;
                    char cardAsString[5];
                    sprintf(cardAsString, "%i", cardAsNumber);
                    strcpy(stringCardNum,cardAsString);
                }
            }
            if(i == 0) {
                strcpy(playerStringCardNum, stringCardNum);
            } else {
                strcpy(cpuStringCardNum, stringCardNum);
            }

            char cardColor[5];


            switch ( ((*pCurrentSideCards)+i )->is_red_card) {
                case 0:
                strcpy(cardColor, "black");
                break;
                case 1:
                strcpy(cardColor, "red");
            }

            if(i == 0) {
                strcpy(playerCardColor, cardColor);
            } else {
                strcpy(cpuCardColor, cardColor);
            }
        }
            //The error comes right here before printing out the results somewhere
            printf("                     RESULTS!!! (DUN DUN, DUN)");
            printf("\n       Card Color        Card Number         Card Suit");
            printf("\n YOU: A %s                 %s          of      %s     ", playerCardColor, playerStringCardNum, playerCardSuit);
            printf("\n CPU:  A %s                 %s          of      %s    " , cpuCardColor, cpuStringCardNum, cpuCardSuit);
    }

    free(pPlayerCards);
    return 0;
}
void deal_cards_to_cpu(struct card *pCpuCards, int cardsToDeal) {
    printf("\nPlease Wait...We are giving your opponent a good hand\n");
    waitFor(1);
    int numbersDealedSinceResponse = 0;
    float randNumsNeeded = 3 * cardsToDeal; //3 values to assign per card in the deck
    float totalNumsDealed = 0.0;

    for (int i = 0; i < cardsToDeal; i++) {
        //Get suit for card
        int suitNum = get_random_number_above_zero(4);
        //Get card number
        int cardNum = get_random_number_above_zero(13);
        //Tell if the card is red
        int isRed = (get_random_number_above_zero(2)) - 1;

        //Find the current card and assign the correct values
        (pCpuCards+i)->current_card_suit = suitNum;
        (pCpuCards+i)->card_num = cardNum;
        (pCpuCards+i)->is_red_card = isRed;
        printf("\n\nFor debugging purposes only, here are the CPU cards generated");
        printf("\nSuit Num: %i", suitNum);
        printf("\nCardNum: %i", cardNum);
        printf("\nIs it red: %i\n", isRed);
        if(numbersDealedSinceResponse > 6) {
            //delay and then change seed; see comment in deal_cards_to_player() for explanation
            waitFor(1);
            srand(time(NULL));
        }
        if(numbersDealedSinceResponse == 12) {
            //After 12 cards, give the user feedback on our progress by % done
            float percent_done = 100 * (totalNumsDealed / randNumsNeeded);;
            int percent_rounded = (int) percent_done;
            printf("Please Wait...We are giving your opponent a good hand (%i%%)\n", percent_rounded);
            numbersDealedSinceResponse = 0;
            totalNumsDealed += 12;
        }
        numbersDealedSinceResponse+=3;
    }
}
void deal_cards_to_player(struct card *pPlayerCard, int cardsToDeal) {
    printf("\nPlease Wait...We are dealing out your cards\n");
    waitFor(1);
    int numbersDealedSinceResponse = 0;
    float randNumsNeeded = 3 * cardsToDeal; //You need three random values shown in the struct for each card
    float totalNumsDealed = 0.0;

    for (int i = 0; i < cardsToDeal; i++) {
        //Get suit for card
        int suitNum = get_random_number_above_zero(4);
        //Get card number
        int cardNum = get_random_number_above_zero(13);
        //Tell if the card is red
        int isRed = (get_random_number_above_zero(2)) - 1;
        //Assign the values after getting the current card in the array
        (pPlayerCard+i)->current_card_suit = suitNum;
        (pPlayerCard+i)->card_num = cardNum;
        (pPlayerCard+i)->is_red_card = isRed;
        printf("\n\nFor debugging purposes only, here are the player cards generated:");
        printf("\nSuit Num: %i", suitNum);
        printf("\nCardNum: %i", cardNum);
        printf("\nIs it red: %i", isRed);
        if(numbersDealedSinceResponse > 6) {


        /* In order for the random numbers to stay unique and not be
        generated in a pattern, wait for one second and then call srand(time(NULL));
to change the seed again based on time every 6 numbers */
                waitFor(1);
                srand(time(NULL));
            }
            if(numbersDealedSinceResponse == 12) {
                //Every 12 numbers provide a response showing the percent completed
                float percent_done = 100 * (totalNumsDealed / randNumsNeeded);;
                int percent_rounded = (int) percent_done;
                printf("Please Wait...We are dealing out your cards (%i%%)\n", percent_rounded);
                numbersDealedSinceResponse = 0;
                totalNumsDealed += 12;
            }
            numbersDealedSinceResponse+=3;
    }
}

int get_random_number_above_zero(int max_num) {
    int randomNumber;
    randomNumber = (rand() % max_num) + 1;
    return randomNumber;
}

void waitFor(unsigned int seconds) {
    unsigned int stopTime = time(0) + seconds;
    while (time(0) < stopTime); //it will wait until the calculated stop time
}

(对于代码转储,我深表歉意;我想确保可以重现该问题)

代码中的问题

我已经测试了将 运行dom 卡属性分配给每副牌的代码,并且 发现分配的值是正确的 。我试图通过在确定卡片字符串时基本上循环两次来避免创建重复代码,并且我尝试创建一个指向卡片结构指针的指针。这是发生的情况的测试 运行 示例:

Enter the amount of cards you would like to be sealed to each player
for the war game (between 0 and 100)

    50

    Press enter once more to proceed...

    Please Wait...We are dealing out your cards


    For debugging purposes only, here are the player cards generated:
    Suit Num: 2
    CardNum: 3
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 12
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 2
    CardNum: 11
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 11
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 1
    CardNum: 13
    Is it red: 1
    Please Wait...We are dealing out your cards (0%)


    For debugging purposes only, here are the player cards generated:
    Suit Num: 4
    CardNum: 4
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 2
    CardNum: 13
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 2
    CardNum: 2
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 8
    Is it red: 1
    Please Wait...We are dealing out your cards (8%)


    For debugging purposes only, here are the player cards generated:
    Suit Num: 2
    CardNum: 12
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 12
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 1
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 1
    CardNum: 3
    Is it red: 0
    Please Wait...We are dealing out your cards (16%)


    For debugging purposes only, here are the player cards generated:
    Suit Num: 4
    CardNum: 7
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 4
    CardNum: 8
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 10
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 1
    Is it red: 0
    Please Wait...We are dealing out your cards (24%)


    For debugging purposes only, here are the player cards generated:
    Suit Num: 2
    CardNum: 5
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 4
    CardNum: 4
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 9
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 1
    CardNum: 9
    Is it red: 1
    Please Wait...We are dealing out your cards (32%)


    For debugging purposes only, here are the player cards generated:
    Suit Num: 4
    CardNum: 13
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 1
    CardNum: 13
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 5
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 4
    Is it red: 1
    Please Wait...We are dealing out your cards (40%)


    For debugging purposes only, here are the player cards generated:
    Suit Num: 2
    CardNum: 8
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 2
    CardNum: 9
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 1
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 1
    CardNum: 12
    Is it red: 0
    Please Wait...We are dealing out your cards (48%)


    For debugging purposes only, here are the player cards generated:
    Suit Num: 4
    CardNum: 3
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 5
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 13
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 10
    Is it red: 0
    Please Wait...We are dealing out your cards (56%)


    For debugging purposes only, here are the player cards generated:
    Suit Num: 2
    CardNum: 1
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 4
    CardNum: 1
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 9
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 1
    CardNum: 5
    Is it red: 1
    Please Wait...We are dealing out your cards (64%)


    For debugging purposes only, here are the player cards generated:
    Suit Num: 4
    CardNum: 9
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 1
    CardNum: 10
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 5
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 13
    Is it red: 1
    Please Wait...We are dealing out your cards (72%)


    For debugging purposes only, here are the player cards generated:
    Suit Num: 2
    CardNum: 4
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 2
    CardNum: 6
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 4
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 1
    CardNum: 8
    Is it red: 0
    Please Wait...We are dealing out your cards (80%)


    For debugging purposes only, here are the player cards generated:
    Suit Num: 4
    CardNum: 12
    Is it red: 0

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 2
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 13
    Is it red: 1

    For debugging purposes only, here are the player cards generated:
    Suit Num: 3
    CardNum: 6
    Is it red: 0
    Please Wait...We are dealing out your cards (88%)


    For debugging purposes only, here are the player cards generated:
    Suit Num: 2
    CardNum: 10
    Is it red: 1
    Please Wait...We are giving your opponent a good hand


    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 11
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 3
    CardNum: 9
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 1
    CardNum: 12
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 13
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 5
    Is it red: 1
    Please Wait...We are giving your opponent a good hand (0%)


    For debugging purposes only, here are the CPU cards generated
    Suit Num: 3
    CardNum: 9
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 3
    CardNum: 13
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 11
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 2
    CardNum: 13
    Is it red: 0
    Please Wait...We are giving your opponent a good hand (8%)


    For debugging purposes only, here are the CPU cards generated
    Suit Num: 1
    CardNum: 4
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 9
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 10
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 11
    Is it red: 0
    Please Wait...We are giving your opponent a good hand (16%)


    For debugging purposes only, here are the CPU cards generated
    Suit Num: 3
    CardNum: 2
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 1
    CardNum: 5
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 6
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 2
    CardNum: 6
    Is it red: 0
    Please Wait...We are giving your opponent a good hand (24%)


    For debugging purposes only, here are the CPU cards generated
    Suit Num: 1
    CardNum: 10
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 2
    CardNum: 1
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 5
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 1
    Is it red: 1
    Please Wait...We are giving your opponent a good hand (32%)


    For debugging purposes only, here are the CPU cards generated
    Suit Num: 3
    CardNum: 5
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 3
    CardNum: 10
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 1
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 2
    CardNum: 9
    Is it red: 1
    Please Wait...We are giving your opponent a good hand (40%)


    For debugging purposes only, here are the CPU cards generated
    Suit Num: 1
    CardNum: 13
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 6
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 10
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 7
    Is it red: 0
    Please Wait...We are giving your opponent a good hand (48%)


    For debugging purposes only, here are the CPU cards generated
    Suit Num: 3
    CardNum: 11
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 1
    CardNum: 2
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 9
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 2
    CardNum: 2
    Is it red: 0
    Please Wait...We are giving your opponent a good hand (56%)


    For debugging purposes only, here are the CPU cards generated
    Suit Num: 1
    CardNum: 6
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 2
    CardNum: 11
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 5
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 10
    Is it red: 1
    Please Wait...We are giving your opponent a good hand (64%)


    For debugging purposes only, here are the CPU cards generated
    Suit Num: 3
    CardNum: 1
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 3
    CardNum: 7
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 1
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 2
    CardNum: 5
    Is it red: 1
    Please Wait...We are giving your opponent a good hand (72%)


    For debugging purposes only, here are the CPU cards generated
    Suit Num: 1
    CardNum: 12
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 3
    CardNum: 3
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 13
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 3
    Is it red: 0
    Please Wait...We are giving your opponent a good hand (80%)


    For debugging purposes only, here are the CPU cards generated
    Suit Num: 3
    CardNum: 7
    Is it red: 0

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 4
    CardNum: 12
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 1
    CardNum: 9
    Is it red: 1

    For debugging purposes only, here are the CPU cards generated
    Suit Num: 2
    CardNum: 11
    Is it red: 0
    Please Wait...We are giving your opponent a good hand (88%)


    For debugging purposes only, here are the CPU cards generated
    Suit Num: 1
    CardNum: 2
    Is it red: 1

    Wow! My hand is SO tired of dealing all those cards.  Let's play!

        3, 2, 1, GO, GO, GO!!!

[PROGRAM STOPS UNEXPECTEDLY BEFORE PRINTING OUT RESULTS]

Abort trap: 6

当我试图将 运行domly 生成的数字转换为单词时,让我相信我正在访问不属于我的内存。我 认为 当我尝试创建指向卡片结构数组的指针并在此处决定时,我的问题发生了:

struct card **pCurrentSideCards

当我根据 for 循环迭代决定时:

 if(i == 0) {
    pCurrentSideCards = &pPlayerCards;
 } else {
    pCurrentSideCards = &pCpuCards;
 }

最后,当我尝试使用 switch 语句访问值时

 switch ( ((*pCurrentSideCards)+i)->current_card_suit)

这种尝试删除重复代码的方法有问题吗?这是我代码中的错误所在吗?

你有很多错误。

以下来源更正了其中的一些内容。然而,一个根本的缺陷是你需要创建一副 52 张牌,然后从这副牌中随机 select 而不更换。相反,您正在随机生成单张卡片,这可能会导致卡片重复。

一个变化是使它实际上编译为 C 程序而不是 C++。由于代码中散布着变量定义,我遇到了编译器错误,但后来我使用的是旧版编译器。

这纠正了原始问题中原始来源的一些问题。希望对你有帮助。

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

enum suit {
    heart = 0,
    spade = 1,
    club = 2,
    diamond = 3
};

char *suitNames[] = {   // must correspond to the enum suit {} above.
        "hearts",       // position 0 or heart
        "spades",       // position 1 or spade
        "clubs",        // position 2 or club
        "diamonds"      // position 3 or diamond
};

struct card {
    enum suit current_card_suit;
    int card_num;
    int is_red_card;
};

int cardDeckSize = 0;

int numOpponentCardsLeft;
int numPlayerCardsLeft;

void deal_cards_to_player (struct card * pPlayerCards, int cardDeckSize);
void deal_cards_to_cpu (struct card * pCpuCards, int cardDeckSize);

int get_random_number_above_zero(int max);
void waitFor(unsigned int seconds);

void flush_input() {
    int ch;
    while ((ch = getchar()) != '\n' && ch != EOF)
    continue;
}

int main (int argc, char **argv) {

    int random_suit;
    char userInput[10];
    //Get deck size for war game
    int invalidSize = 1;
    int i, j;

    //Create arrays to hold the cards of the player and CPU
    struct card *pPlayerCards;
    struct card *pCpuCards;
    struct card *pCurrentSideCards;

    //Get Random number sequence for later
    srand(time(NULL));
    while (invalidSize == 1) {
        printf("\nEnter the amount of cards you would like to be dealed to each player for the war game (between 0 and 100)\n");

        fgets(userInput, 9, stdin);

        if(sscanf(userInput, "%i", &cardDeckSize) != 1) {
            printf("\nPlease enter an integer. You will have to enter the number twice because you did not follow directions.\n");
            flush_input();
            continue;
        }
        if(cardDeckSize > 0 && cardDeckSize < 101) {
            invalidSize = 0;
            break;
        } else {
            printf("\nPlease type a number between 0 and 100. You will have to enter the number twice because you did not follow directions.\n");
            flush_input();
            continue;
        }
    }
    printf("\nPress enter once more to proceed...");
    flush_input();

    pPlayerCards = malloc (cardDeckSize * sizeof(struct card));
    pCpuCards = malloc (cardDeckSize * sizeof(struct card));

    //You will see duplication in the two functions called below, but I could not figure out how to remove it; it works for now
    deal_cards_to_player(pPlayerCards, cardDeckSize);
    deal_cards_to_player(pCpuCards, cardDeckSize);
//    deal_cards_to_cpu(pCpuCards, cardDeckSize);

    printf("\nWow! My hand is SO tired of dealing all those cards.  Let's play!\n\n");

    //"parse" the properties of each card...and right after show the game round results to the player
    /* I will have to change "i < cardDeckSize" eventually becuase the size of the deck will not necessarily determine
     the # of rounds; I'll get through one round first before worrying about this */
    for(i = 0; i < cardDeckSize; i++) { //Loop through each round

        char playerCardSuit[12] = {0};
        char cpuCardSuit[12] = {0};

        char playerStringCardNum[12] = {0};
        char cpuStringCardNum[12] = {0};

        char playerCardColor[12] = {0};
        char cpuCardColor[12] = {0};
        char stringCardNum[12] = {0};

        //Countdown for the player
        printf("\n3, ");
        waitFor(1);
        printf("2, ");
        waitFor(1);
        printf("1, ");
        waitFor(1);
        printf("GO, GO, GO!!!\n");
        waitFor(1);

        //Determine card terms set for each player
        for (j = 0; j < 2; j++) {
            char cardSuit[12] = {0};
            char cardColor[12] = {0};

            /* To eliminate duplication, based on the current iteration I tried to
            create a pointer that points to a pointer to the array of card structures
            for each player. we need to index through the hand to each card dealt */
            if(j == 0) {
                //Start with "parsing" the player cards, then the CPU cards
                pCurrentSideCards = pPlayerCards + i;
            } else {
                pCurrentSideCards = pCpuCards + i;
            }

            //EXPLANATION:
            /* Accessing the card properties: I first tried to dereference the pointer
            to find a pointer to the card deck structure array.  Then I accessed
            the correct card member in the array with "+i".  I finally tried
            to access the value with the "->" symbol, which dereferences again
 before accessing the member
            */
            if ( pCurrentSideCards->current_card_suit <= diamond) {
                strcpy (cardSuit, suitNames[pCurrentSideCards->current_card_suit]);
            } else {
               printf("\nThere was a fatal error determining the card suit of some dealt out cards.\n");
            }
            if(j == 0) { //If i = 0 we are working with the player cards, otherwise we are working with the CPU cards
                strcpy(playerCardSuit, cardSuit);
            } else {
                strcpy(cpuCardSuit, cardSuit);
            }

            switch (pCurrentSideCards->card_num) {
                case 1:
                    strcpy(stringCardNum, "ace");
                    break;

                case 11:
                    strcpy(stringCardNum, "jack");
                    break;

                case 12:
                    strcpy(stringCardNum, "queen");
                    break;

                case 13:
                    strcpy(stringCardNum, "king");
                    break;

                default: {
                    int cardAsNumber = pCurrentSideCards->card_num;
                    char cardAsString[12] = {0};
                    sprintf(cardAsString, "%i", cardAsNumber);
                    strcpy(stringCardNum,cardAsString);
                }
            }
            if(j == 0) {
                strcpy(playerStringCardNum, stringCardNum);
            } else {
                strcpy(cpuStringCardNum, stringCardNum);
            }

            switch (pCurrentSideCards->is_red_card) {
                case 0:
                    strcpy(cardColor, "black");
                    break;
                case 1:
                    strcpy(cardColor, "red");
                    break;
            }

            if(j == 0) {
                strcpy(playerCardColor, cardColor);
            } else {
                strcpy(cpuCardColor, cardColor);
            }
        }

        printf("\n               RESULTS!!! (DUN DUN, DUN)");
        printf("\n         Card Color        Card Number         Card Suit");
        printf("\n YOU:  A   %-8.8s             %-8.8s     of      %s     ", playerCardColor, playerStringCardNum, playerCardSuit);
        printf("\n CPU:  A   %-8.8s             %-8.8s     of      %s    " , cpuCardColor, cpuStringCardNum, cpuCardSuit);
    }

    free(pPlayerCards);
    return 0;
}

void deal_cards_to_player(struct card *pPlayerCard, int cardsToDeal) {
    int numbersDealedSinceResponse = 0;
    float randNumsNeeded = 3 * cardsToDeal; //You need three random values shown in the struct for each card
    float totalNumsDealed = 0.0;
    int i;

    printf("\nPlease Wait...We are dealing out your cards\n");
    waitFor(1);
    for (i = 0; i < cardsToDeal; i++) {
        //Get suit for card as a value from 0 to 3.
        int suitNum = get_random_number_above_zero(4) - 1;
        //Get card number
        int cardNum = get_random_number_above_zero(13);
        //Tell if the card is red based on the suit number
        // red if hearts or diamonds.
        int isRed = (suitNum == 0 || suitNum == 3);
        //Assign the values after getting the current card in the array
        (pPlayerCard+i)->current_card_suit = suitNum;
        (pPlayerCard+i)->card_num = cardNum;
        (pPlayerCard+i)->is_red_card = isRed;
        printf("\n\nFor debugging purposes only, here are the player cards generated:");
        printf("\nSuit Num: %i", suitNum);
        printf("\nCardNum: %i", cardNum);
        printf("\nIs it red: %i", isRed);
        if(numbersDealedSinceResponse > 6) {
            /* In order for the random numbers to stay unique and not be
            generated in a pattern, wait for one second and then call srand(time(NULL));
            to change the seed again based on time every 6 numbers */
            waitFor(1);
        }
        if(numbersDealedSinceResponse == 12) {
                //Every 12 numbers provide a response showing the percent completed
                float percent_done = 100 * (totalNumsDealed / randNumsNeeded);
                int percent_rounded = (int) percent_done;
                printf("Please Wait...We are dealing out your cards (%i%%)\n", percent_rounded);
                numbersDealedSinceResponse = 0;
                totalNumsDealed += 12;
        }
        numbersDealedSinceResponse+=3;
    }
}

int get_random_number_above_zero(int max_num) {
    int randomNumber;
    randomNumber = (rand() % max_num) + 1;
    return randomNumber;
}

void waitFor(unsigned int seconds) {
    unsigned int stopTime = time(0) + seconds;
    while (time(0) < stopTime); //it will wait until the calculated stop time
}