I am new to learning about C, so as an exercise I attempted to create a text-based card game where each person/CPU places down a random card at the top of their deck, and the person with the higher card will take the card and add it to their deck. During a tie, both cards would be discarded. When a person reaches zero cards, in this game they will lose. It is basically a simplified version of the war card game.
I came across a problem soon after I started developing. Here is the code I had until I ran across my error:
#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
}
(I apologize for the code dump; I wanted to make sure it was possible to reproduce the problem)
I have tested the code that assigns random card properties to each deck of cards, and have found the values assigned to be ok. I attempted to avoid creating duplicate code by basically looping two times when determining the card strings, and I tried to create a pointer to the pointer to the structure of cards. Here is a test run example of what happens:
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
Leading me to believe I am accessing memory I do not own when I tried to convert the randomly generated numbers into words. I think my problem happens when I try to create my pointer that points to the pointer to the array of the card structure and decide here:
struct card **pCurrentSideCards
And when I decide based on the for loop iteration:
if(i == 0) {
pCurrentSideCards = &pPlayerCards;
} else {
pCurrentSideCards = &pCpuCards;
}
Finally, when I try to access the values with the switch statements
switch ( ((*pCurrentSideCards)+i)->current_card_suit)
Is there a problem with this approach to try to remove the duplicate code? Is this where the error in my code is?
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
}