/* * game.cpp * * */ #include "game.h" #include /* forward declaration of hands array, very interesting, I didn't know C++ needs this */ string *Game::hands[10]; string *Game::suits[5]; Game::Game(void) { hands[0] = new string("Royal Flush"); hands[1] = new string("Straight Flush"); hands[2] = new string("Four of a Kind"); hands[3] = new string("Full House"); hands[4] = new string("Flush"); hands[5] = new string("Straight"); hands[6] = new string("Three of a Kind"); hands[7] = new string("Two Pair"); hands[8] = new string("One Pair"); hands[9] = new string("High Card"); suits[0] = new string("Undefined"); suits[1] = new string("Clubs"); suits[2] = new string("Diamonds"); suits[3] = new string("Hearts"); suits[4] = new string("Spades"); } void Game::shufflePile(void) { /* interesting algorithm that was discussed in the class */ Card *tmp; int i, j; for (i = 0; i < 52; i++) { j = rand() % 52; tmp = getCardFromDeck(i); putCardToDeck(i, getCardFromDeck(j)); putCardToDeck(j, tmp); } } int Game::parseInt(string *msg, int rangeA, int rangeB) { int tmp; bool continueAsking = true; while (continueAsking) { if (msg) cout << *msg; if (!(cin >> tmp)) { cin.clear(); cin.ignore(std::numeric_limits::max(), '\n'); PRINT_COLOR(ANSI_COLOR_RED, "Invalid input!\n"); continue; } if ((tmp >= rangeA) && (tmp <= rangeB)) continueAsking = false; else PRINT_COLOR(ANSI_COLOR_YELLOW, "Number not in the range!\n"); } return tmp; } void Game::askForNumberOfOpponents(void) { bool continueAsking = true; while (continueAsking) { cout << "Enter the amount of opponents between 1 to 3: "; if (!(cin >> numOfOpponents)) { cin.clear(); cin.ignore(std::numeric_limits::max(), '\n'); PRINT_COLOR(ANSI_COLOR_RED, "Invalid character(s)!\n"); continue; } if ((numOfOpponents >= 1) && (numOfOpponents <= 3)) continueAsking = false; else PRINT_COLOR(ANSI_COLOR_YELLOW, "Number not in the range!\n"); } } void Game::repeatGame(bool *quit) { bool continueAsking = true; char play_again; cout << endl; while (continueAsking) { PRINT_COLOR(ANSI_COLOR_GREEN, "Play again? (y/n) "); cin >> play_again; play_again = tolower(play_again); if (play_again == 'y') continueAsking = false; else if (play_again == 'n') { continueAsking = false; *quit = true; } } } int Game::howManyCardsOfSameSuit(Card **cards) { if (cards == NULL) { PRINT_COLOR(ANSI_COLOR_RED, "\nhowManyCardsOfSameSuit(): cards parameter is NULL!\n"); return -1; } char c, l; l = cards[0]->getType()[1]; int i; for (i = 1; i < 5; i++) { c = cards[i]->getType()[1]; if (c != l) break; } return i; } bool Game::pairOrBetter(Card **cards) { if (cards == NULL) { PRINT_COLOR(ANSI_COLOR_RED, "\npairOrBetter(): cards parameter is NULL!\n"); return false; } char c1, c2; int ret = 0; int i, j; for (i = 0; i < 5; i++) { c1 = cards[i]->getType()[0]; for (j = i+1; j < 5; j++) { c2 = cards[j]->getType()[0]; if (c1 == c2) { ret++; break; } } } return (ret != 0); } /* returns max number of same cards, returns 0 when all cards are different */ int Game::numOfSameCards(Card **cards) { if (cards == NULL) { PRINT_COLOR(ANSI_COLOR_RED, "\nnumOfSameCards(): cards parameter is NULL!\n"); return -1; } char c1, c2; int same = 0; int max = 0; int i, j; for (i = 0; i < 5; i++) { c1 = cards[i]->getType()[0]; for (j = i+1; j < 5; j++) { c2 = cards[j]->getType()[0]; same = 1; if (c1 == c2) { same++; if (same > max) max = same; } else { same = 0; c1 = c2; } } } return max; } struct countAndSuit Game::numOfSameSuit(Card **cards) { struct countAndSuit same[5] = { { Clubs, 0}, { Diamond, 0 }, { Hearts, 0 }, { Spades, 0 }, { Undef, -1 }, }; if (cards == NULL) { PRINT_COLOR(ANSI_COLOR_RED, "\nnumOfSameSuit(): cards parameter is NULL!\n"); return same[4]; } int max = 0; enum Suit tmpSuit = Undef; /* go through all cards and count how many there is of each suit */ int i; for (i = 0; i < 5; i++) { tmpSuit = cards[i]->getSuit(); switch (tmpSuit) { case Clubs: same[0].count += 1; break; case Diamond: same[1].count += 1; break; case Hearts: same[2].count += 1; break; case Spades: same[3].count += 1; break; default: cout << "could not determine the suit of the card" << endl; } } int whereMaxWasFound = 0; /* look for the max number of cards of the same suit */ for (i = 0; i < 4; i++) if (same[i].count > max) { max = same[i].count; whereMaxWasFound = i; } return same[whereMaxWasFound]; } bool Game::doWeHaveAnAce(Card **cards) { if (cards == NULL) { PRINT_COLOR(ANSI_COLOR_RED, "\ndoWeHaveAnAce(): cards parameter is NULL!\n"); return false; } char c; int i; for (i = 0; i < 5; i++) { c = cards[i]->getType()[0]; if (c == 'A') return true; } return false; } void Game::discardAndDraw(Card **cards, int amount, int offset) { if (offset + amount > 5) { PRINT_COLOR(ANSI_COLOR_RED, "amount of cards to be discarded is out of bounds!\n"); return; } else if (cards == NULL) { PRINT_COLOR(ANSI_COLOR_RED, "\ndiscardAndDraw(): cards parameter is NULL!\n"); return; } int i; /* discard cards starting from offset */ for (i = 0; i < amount; i++) { #ifdef DEBUG cout << ANSI_COLOR_CYAN << "debug: discarding card " << i+1 << " \"" << cards[offset+i]->getType() << "\" at cards[" << offset+i << "]" << endl << ANSI_COLOR_RESET; #endif putCardToDiscardPile(cards[offset+i]); } /* draw cards from the deck into starting at cards[offset] */ for (i = 0; i < amount; i++) { cards[offset+i] = PopCardFromDeck(); #ifdef DEBUG cout << ANSI_COLOR_CYAN << "debug: drawing card " << i+1 << " \"" << cards[offset+i]->getType() << "\" into cards[" << offset+i << "]" << endl << ANSI_COLOR_RESET; #endif } } void Game::opponentAI(Card **cards) { if (cards == NULL) { PRINT_COLOR(ANSI_COLOR_RED, "\ngetopponentAI(): cards parameter is NULL!\n"); return; } struct countAndSuit tmp = numOfSameSuit(cards); if (pairOrBetter(cards)) { PRINT_COLOR(ANSI_COLOR_CYAN, "\ndebug: opponentAI, there's a pair or better\n"); /* discard 4 other cards*/ return; } else if ( (tmp = numOfSameSuit(cards)).count == 5) { PRINT_COLOR(ANSI_COLOR_CYAN, "\ndebug: opponentAI, 5 cards are of the same suit!\n"); /* keep 5 cards of the same suit */ return; } else if (tmp.count == 4) { PRINT_COLOR(ANSI_COLOR_CYAN, "\ndebug: opponentAI, 4 cards are of the same suit\n"); /* keep 4 cards of the same suit and discard 1 of different suit */ /* we need to loop through cards[] and find a card with different suit */ int i; for (i = 0; i < 5; i++) { if (cards[i]->getSuit() != tmp.whatSuit) break; } /* no i should be the index of card that we want to discard */ discardAndDraw(cards, 1, i); return; } else if (doWeHaveAnAce(cards)) { PRINT_COLOR(ANSI_COLOR_CYAN, "\ndebug: opponentAI, High Hand with Ace detected\n"); /* discard 4 cards */ discardAndDraw(cards, 4, 1); return; } else { PRINT_COLOR(ANSI_COLOR_CYAN, "\ndebug: opponentAI, High Hand detected\n"); /* discard 3 cards */ discardAndDraw(cards, 3, 2); } PRINT_COLOR(ANSI_COLOR_RED, "\nopponentAI(): cards did not match any of the criterias!\n"); }