0

私は C について学ぶのが初めてなので、演習として、各人/CPU がランダムなカードをデッキの一番上に置き、より高いカードを持つ人がカードを取るテキストベースのカードゲームを作成しようとしましたそしてそれを自分のデッキに加える。同点の場合、両方のカードが破棄されます。このゲームでは、手札がゼロになると負けとなります。基本的にはウォーカードゲームの簡易版です。

開発を始めてすぐに問題が発生しました。エラーに遭遇するまでのコードは次のとおりです。

#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
}

(コード ダンプをお詫びします。問題を再現できることを確認したかったのです)

コードの問題

カードの各デッキにランダムなカード プロパティを割り当てるコードをテストしたところ、割り当てられた値が ok であることがわかりました。カードの文字列を決定するときは、基本的に 2 回ループすることで重複コードを作成しないようにし、カードの構造へのポインターへのポインターを作成しようとしました。何が起こるかのテスト実行例を次に示します。

各プレイヤーに封印したいカードの枚数を入力してください
戦争ゲーム用 (0 から 100 の間)

    50

    Enter キーをもう一度押して続行します...

    お待ちください...カードを配っています


    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 2
    カード番号: 3
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 12
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 2
    カード番号: 11
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 11
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 1
    カード番号: 13
    赤ですか: 1
    お待ちください...あなたのカードを配っています (0%)


    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 4
    カード番号: 4
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 2
    カード番号: 13
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 2
    カード番号: 2
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 8
    赤ですか: 1
    お待ちください...あなたのカードを配っています (8%)


    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 2
    カード番号: 12
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 12
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 1
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 1
    カード番号: 3
    赤ですか: 0
    お待ちください...あなたのカードを配っています (16%)


    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 4
    カード番号: 7
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 4
    カード番号: 8
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 10
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 1
    赤ですか: 0
    お待ちください...あなたのカードを配っています (24%)


    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 2
    カード番号: 5
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 4
    カード番号: 4
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 9
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 1
    カード番号: 9
    赤ですか: 1
    お待ちください...あなたのカードを配っています (32%)


    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 4
    カード番号: 13
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 1
    カード番号: 13
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 5
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 4
    赤ですか: 1
    お待ちください...あなたのカードを配っています (40%)


    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 2
    カード番号: 8
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 2
    カード番号: 9
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 1
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 1
    カード番号: 12
    赤ですか: 0
    お待ちください...あなたのカードを配っています (48%)


    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 4
    カード番号: 3
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 5
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 13
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 10
    赤ですか: 0
    お待ちください...あなたのカードを配っています (56%)


    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 2
    カード番号: 1
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 4
    カード番号: 1
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 9
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 1
    カード番号: 5
    赤ですか: 1
    お待ちください...あなたのカードを配っています (64%)


    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 4
    カード番号: 9
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 1
    カード番号: 10
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 5
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 13
    赤ですか: 1
    お待ちください...あなたのカードを配っています (72%)


    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 2
    カード番号: 4
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 2
    カード番号: 6
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 4
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 1
    カード番号: 8
    赤ですか: 0
    お待ちください...あなたのカードを配っています (80%)


    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 4
    カード番号: 12
    赤ですか: 0

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 2
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 13
    赤ですか: 1

    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 3
    カード番号: 6
    赤ですか: 0
    お待ちください...あなたのカードを配っています (88%)


    デバッグのみを目的として、生成されたプレイヤー カードを以下に示します。
    スーツ番号: 2
    カード番号: 10
    赤ですか: 1
    お待ちください...対戦相手に良い手を差し上げています


    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 11
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 3
    カード番号: 9
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 1
    カード番号: 12
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 13
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 5
    赤ですか: 1
    お待ちください...対戦相手に良い手札を差し上げています (0%)


    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 3
    カード番号: 9
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 3
    カード番号: 13
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 11
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 2
    カード番号: 13
    赤ですか: 0
    お待ちください...対戦相手に良い手札を与えています (8%)


    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 1
    カード番号: 4
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 9
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 10
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 11
    赤ですか: 0
    お待ちください...対戦相手に良い手を差し伸べています (16%)


    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 3
    カード番号: 2
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 1
    カード番号: 5
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 6
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 2
    カード番号: 6
    赤ですか: 0
    お待ちください...対戦相手に良い手札を与えています (24%)


    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 1
    カード番号: 10
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 2
    カード番号: 1
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 5
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 1
    赤ですか: 1
    お待ちください...対戦相手に良い手札を与えています (32%)


    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 3
    カード番号: 5
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 3
    カード番号: 10
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 1
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 2
    カード番号: 9
    赤ですか: 1
    お待ちください...対戦相手に良い手札を差し上げています (40%)


    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 1
    カード番号: 13
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 6
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 10
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 7
    赤ですか: 0
    お待ちください...対戦相手に良い手を差し伸べています (48%)


    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 3
    カード番号: 11
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 1
    カード番号: 2
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 9
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 2
    カード番号: 2
    赤ですか: 0
    お待ちください...対戦相手に良い手札を与えています (56%)


    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 1
    カード番号: 6
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 2
    カード番号: 11
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 5
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 10
    赤ですか: 1
    お待ちください...対戦相手に良い手札を与えています (64%)


    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 3
    カード番号: 1
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 3
    カード番号: 7
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 1
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 2
    カード番号: 5
    赤ですか: 1
    お待ちください...対戦相手に良い手札を与えています (72%)


    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 1
    カード番号: 12
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 3
    カード番号: 3
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 13
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 3
    赤ですか: 0
    お待ちください...対戦相手に良い手札を与えています (80%)


    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 3
    カード番号: 7
    赤ですか: 0

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 4
    カード番号: 12
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 1
    カード番号: 9
    赤ですか: 1

    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 2
    カード番号: 11
    赤ですか: 0
    お待ちください...対戦相手に良い手を差し伸べています (88%)


    デバッグのみを目的として、生成された CPU カードを以下に示します。
    スーツ番号: 1
    カード番号: 2
    赤ですか: 1

    わお!私のハンドは、それらすべてのカードを配るのにうんざりしています。遊ぼう!

        3、2、1、GO、GO、GO!!!

[PROGRAM STOPS UNEXPECTEDLY BEFORE PRINTING OUT RESULTS]

アボートトラップ: 6

ランダムに生成された数字を単語に変換しようとすると、自分が所有していないメモリにアクセスしていると思い込んでしまいます。カード構造の配列へのポインターを指すポインターを作成しようとすると、問題が発生すると思います。ここで決定します。

struct card **pCurrentSideCards

そして、for ループの反復に基づいて決定すると、次のようになります。

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

最後に、switch ステートメントで値にアクセスしようとすると、

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

重複したコードを削除しようとするこのアプローチに問題はありますか? これは私のコードのエラーの場所ですか?

4

1 に答える 1

1

You have a number of mistakes.

The following source corrects some of them. However a fundamental defect is that you need to create a deck of 52 cards and then randomly select from the deck without replacement. You are instead doing random generation of individual cards which can result in duplicated cards.

One change was to make this actually compile as a C program rather C++. I got compiler errors due to the variable definitions scattered through the code but then I am using an older compiler.

This corrects a number of problems with your original source in the original question. I hope this helps you.

#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
}
于 2016-06-12T19:54:28.260 に答える