/* Card Play Demonstration Program, version 1.06, last modified March 25, 1999. */ /* Copyright 1999 by Rick Wagner, all rights reserved. */ /* Source code use with attribution for educational purposes only. */ /* Created for use with Computer Science 101 at USC. */ #include #include #include /* For a random seed */ /* Function prototypes */ void about(); void shuffle(int iDeck[]); void deal(int iDeck[], int iHand[][13]); void sortHand(int iHand[], int iMergeSpace[], int l, int r); void play(int iHand[][13]); void cardName(int iCard, char* sCard); void compactCardArray(int iHand[], int m, int n); int randomInt(int n); void main() { int iPlay = 1; /* True while the user wants to play. */ char cChoice = 0; /* Input choice character. */ int iDeck[52]; /* Deck of cards. */ int iHand[4][13]; /* 13 cards in each of 4 hands. */ about(); /* Seed the random number generator with the system time. */ srand(time(NULL)); /* NULL is defined in stdlib.h. (= 0) */ while (iPlay) /* While the user wants to play: */ { shuffle(iDeck); /* Shuffle the deck. */ deal(iDeck, iHand); /* Deal the hand from the deck. */ play(iHand); /* Play the hand. */ printf("\nPlay again? (y/n) "); scanf("%c", &cChoice); fflush(stdin); if (cChoice != 'y' && cChoice != 'Y') iPlay = 0; printf("\n"); } } void about() { puts(" Card Play Demonstration Program"); puts(" by Rick Wagner\n"); puts(" \6 \3 \4 \5\n"); puts(" Version 1.06 last modified March 25, 1999."); puts(" Copyright 1999 by Rick Wagner, all rights reserved.\n"); puts(" Source code use with attribution for educational purposes only."); puts(" Created for use with Computer Science 101 at USC.\n\n"); } void shuffle(int iDeck[]) { int i = 0; /* Index variables. */ int j = 0; int iSwapSpace = 0; for (i = 0; i < 52; i++) { iDeck[i] = i; /* Fill the array with sequential integers. */ } for (i = 0; i < 52; i++) { j = randomInt(51); iSwapSpace = iDeck[i]; iDeck[i] = iDeck[j]; /* Pick a random card to swap. */ iDeck[j] = iSwapSpace; /* Pick a random card to swap. */ } } void deal(int iDeck[], int iHand[][13]) { int i = 0; /* Index variables. */ int j = 0; int l = 0; /* Left index for merge sort. */ int r = 12; /* Right index for merge sort. */ int iMergeSpace[13]; /* Merge space for merge sort. */ for (i = 0; i < 13; i++) { for (j = 0; j < 4; j++) { iHand[j][i] = iDeck[i * 4 + j]; /* Distribute the cards from */ } /* deck to the hands. */ } /* Sort the hands: */ for (i = 0; i < 4; i++) { sortHand(iHand[i], iMergeSpace, l, r); } } void sortHand(int iHand[], int iMergeSpace[], int l, int r) { /* This is the merge sort discussed in lecture */ int i = 0; int j = 0; int k = 0; int m = 0; int iMinI = 0; int iMaxJ = 0; if (r - l > 0) { m = (r + l) / 2; /* integer division */ sortHand(iHand, iMergeSpace, l, m); sortHand(iHand, iMergeSpace, m + 1, r); for (i = m; i >= l; i--) { iMergeSpace[i] = iHand[i]; iMinI = i; } for (j = m + 1; j <= r; j++) { iMergeSpace[r + m + 1 - j] = iHand[j]; iMaxJ = j; } for (k = l; k <= r; k++) { if (iMergeSpace[iMinI] < iMergeSpace[iMaxJ]) { iHand[k] = iMergeSpace[iMinI]; iMinI++; } else { iHand[k] = iMergeSpace[iMaxJ]; iMaxJ--; } } } } void play(int iHand[][13]) { /* Play the dealt hands: */ int i = 0; /* Loop index */ int j = 0; /* Loop index */ int k = 0; /* Loop index */ char sCard[3]; /* String to display cards */ int iChoice = 0; /* Which card in the hand array is chosen to play. */ int iLead = 3; /* The human starts the play. */ int iPlay = 0; /* Which player has the play. */ int iTrickCount[4] = {0, 0, 0, 0}; /* Count tricks to see who the hand winner is. */ int iSuitLead = 0; /* Players must follow the suit lead if possible. */ int iHighestRankPlayed = 0; /* Highest rank in the suit lead wins the trick. */ int iTrickWinner = 0; /* Which player is the winner of the trick. */ int iCanFollowSuit = 0; /* Player can follow suit */ int iHaveChosen = 0; /* Computer player has chosen a card */ int iMinRank = 0; /* Minimum ranking card to play for a losing trick. */ int iMostTricks = 0; /* Search the trick count array for the most tricks */ int iHandWinner = 0; /* Which player is the winner of the hand */ int iHumanCheatingAttempt = 1; /* Assume the human will try to cheat. */ int iCheatCount = 0; /* Keep track of how many times the human tries to */ /* cheat by not following suit. */ /* Play 13 tricks */ for (i = 13; i >= 1; i--) /* i is the number of cards left in the players' hands */ { /* Lead the first card */ if (iLead == 3) { /* It's the human's lead */ printf("\n\nCards in the human's hand:\n\n"); for (j = 0; j < i; j++) { printf("%3d ", j + 1); } printf("\n"); for (j = 0; j < i; j++) { cardName(iHand[iLead][j], sCard); printf("%s ", sCard); } printf("\n\nYour lead, human. Which card? "); scanf("%d", &iChoice); fflush(stdin); iChoice--; /* Adapt the user's choice for zero-based indexing */ } else { /* One of the computer players has the lead */ iChoice = 0; /* Need an AI function here for better play */ } cardName(iHand[iLead][iChoice], sCard); /* Get a name for the chosen card. */ printf("\nCards played: %s ", sCard); iSuitLead = iHand[iLead][iChoice] / 13; iHighestRankPlayed = iHand[iLead][iChoice] % 13; iTrickWinner = iLead; compactCardArray(iHand[iLead], iChoice, i); /* Compact the hand array. */ /* Play the next three cards */ iPlay = (iLead + 1) % 4; for (j = 1; j <= 3; j++) { if (iPlay == 3) { /* It's the human's play */ printf("\n\nCards in the human's hand:\n\n"); for (k = 0; k < i; k++) { printf("%3d ", k + 1); } printf("\n"); for (k = 0; k < i; k++) { cardName(iHand[iPlay][k], sCard); printf("%s ", sCard); } /* Play the suit lead if possible */ iCanFollowSuit = 0; for (k = 0; k < i; k++) { if (iSuitLead == iHand[iPlay][k] / 13) { iCanFollowSuit = 1; } } iHumanCheatingAttempt = 1; while (iHumanCheatingAttempt) { printf("\n\nYour play, human. Which card? "); scanf("%d", &iChoice); fflush(stdin); iChoice--; /* Adapt the user's choice for zero-based indexing */ if (iChoice > i) iChoice = i; /* Set some bounds for the choice */ if (iChoice < 0) iChoice = 0; if (iCanFollowSuit) { if(iSuitLead == iHand[iPlay][iChoice] / 13) { iHumanCheatingAttempt = 0; /* He's not trying to cheat if he's following suit */ } else { if (iCheatCount == 0) { printf("You must follow suit, human.\n"); } else { if (iCheatCount == 1) { printf("I warned you about trying to cheat once before, human.\n"); } else { if (iCheatCount == 2) { printf("I warned you about cheating twice before, human.\n"); } else { printf("Pathetic human won't learn.\n"); } } } iCheatCount++; } } else { iHumanCheatingAttempt = 0; /* He can't be trying to cheat if he can't follow suit */ } } } else { /* One of the computer players has the play */ iHaveChosen = 0; /* Play the suit lead if possible */ iCanFollowSuit = 0; for (k = 0; k < i; k++) { if (iSuitLead == iHand[iPlay][k] / 13) { iCanFollowSuit = 1; if (iHand[iPlay][k] % 13 > iHighestRankPlayed) { iChoice = k; iHaveChosen = 1; break; /* Break out of for loop. */ } } } if (iHaveChosen) { /* We have our choice which might win this trick. */ } else { /* Need to select a low card because we can't win this trick. */ if (iCanFollowSuit) { /* Pick the lowest card in the lead suit. */ iMinRank = 13; for (k = 0; k < i; k++) { if ((iSuitLead == iHand[iPlay][k] / 13 ) && (iHand[iPlay][k] % 13 < iMinRank)) { iMinRank = iHand[iPlay][k] % 13; iChoice = k; } } } else { /* Pick the lowest ranking card in the hand. */ iMinRank = 13; for (k = 0; k < i; k++) { if (iHand[iPlay][k] % 13 < iMinRank) { iMinRank = iHand[iPlay][k] % 13; iChoice = k; } } } } } cardName(iHand[iPlay][iChoice], sCard); /* Get a name for the chosen card for display. */ printf("%s ", sCard); if ((iHand[iPlay][iChoice] / 13 == iSuitLead) && ((iHand[iPlay][iChoice] % 13) > iHighestRankPlayed)) { iHighestRankPlayed = iHand[iPlay][iChoice] % 13; iTrickWinner = iPlay; } compactCardArray(iHand[iPlay], iChoice, i); /* Compact the hand array. */ iPlay = (iPlay + 1) % 4; } /* End of trick loop (j) */ /* Announce who won the trick. */ if (iTrickWinner == 3) { printf("\n\nYou won that trick, human.\n"); } else { printf("\n\nComputer player %c won the trick.\n", 65 + iTrickWinner); } iTrickCount[iTrickWinner]++; iLead = iTrickWinner; } /* End of hand play for loop (i) */ /* Determine who won the hand. */ iMostTricks = 0; for (i = 0; i <= 3; i++) { if (iTrickCount[i] > iMostTricks) { iMostTricks = iTrickCount[i]; iHandWinner = i; } } printf("\nResults:\n"); printf("Player A: %d tricks.\n", iTrickCount[0]); printf("Player B: %d tricks.\n", iTrickCount[1]); printf("Player C: %d tricks.\n", iTrickCount[2]); printf("Human player: %d tricks.\n", iTrickCount[3]); if (iHandWinner == 3) { printf("\nThe human won the hand.\n"); } else { printf("\nComputer player %c won the hand.\n", 65 + iHandWinner); } } void cardName(int iCard, char* sCard) { /* The string sCard is the name of the card */ int iRank = 0; int iSuit = 0; char* sRank = " "; /* Two characters in case it's a ten */ char cSuit = 0; iRank = iCard % 13; /* Duece through ace. */ iSuit = iCard / 13; /* Integer division for the suit. */ if (iRank == 8) { sRank[0] = '1'; /* Only the ten has two characters for */ sRank[1] = '0'; /* the rank. */ } else { sRank[0] = ' '; if (iRank < 8) { /* It's a duece through nine */ sRank[1] = iRank + 50; /* ASCI 50 is '2'. */ } else { /* We have a face card or an ace. */ switch (iRank) { case 9: { sRank[1] = 'J'; break; } case 10: { sRank[1] = 'Q'; break; } case 11: { sRank[1] = 'K'; break; } case 12: { sRank[1] = 'A'; break; } } } } switch (iSuit) { case 0: { cSuit = 6; /* Spade */ break; } case 1: { cSuit = 3; /* Heart */ break; } case 2: { cSuit = 4; /* Diamond */ break; } case 3: { cSuit = 5; /* Club */ break; } } sCard[0] = sRank[0]; sCard[1] = sRank[1]; sCard[2] = cSuit; } void compactCardArray(int iArray[], int m, int n) { /* m is the hole that needs filling, n is the number of cards */ int i = 0; for (i = m; i < n - 1; i++) /* Compact the card array. */ { iArray[i] = iArray[i + 1]; } } int randomInt(int n) { /* Return a random integer from zero to n: */ return rand() % (n + 1); }