294 lines
No EOL
11 KiB
C++
294 lines
No EOL
11 KiB
C++
/*
|
||
Program Name: Go Fish
|
||
Process: Does the following according to spec:
|
||
Players take turns asking their opponent for a specific card. The game will continue until all sets are
|
||
collected.
|
||
Here are the rules of the game:
|
||
● Use a 52-card deck
|
||
● Deal 7 cards to each player (human and computer).
|
||
Each play will take turns asking for a card rank/number from the opponent. If the opponent has the card
|
||
that is requested, they must hand over all the cards of that rank/number. If the opponent does not have the
|
||
card requested, then the player number “go fish” meaning they must draw a card from the deck. If a
|
||
player collects a set of four cards of the same rank, they will lay down the set and earn a point. The game
|
||
will end when all sets have been collected.
|
||
Function requirements:
|
||
● humanTurn
|
||
○ Handles the human’s turn. It will prompt the player to ask for a card rank/number and
|
||
check if the computer has the requested rank/number. If the card is available in the
|
||
computer’s hand, it will transfer the card to the human’s hand otherwise, it will draw a
|
||
card. The function should return the number of sets collected during the turn
|
||
● computerTurn
|
||
○ Handles the computer’s turn and it should do the same actions as the human but for the
|
||
computer. The function should return the number of set that is collected during its turn.
|
||
Function Input/Parameters: ???
|
||
Function Output/Parameters: ???
|
||
Function Output/Returned: ???
|
||
Device Input/Device: ???
|
||
Device Output/Monitor: ???
|
||
Dependencies: ???
|
||
*/
|
||
|
||
#include <cstdio>
|
||
#include <cstdlib>
|
||
#include <iostream>
|
||
#include <cstring>
|
||
#include <vector>
|
||
#include <random>
|
||
#include <algorithm>
|
||
#include <time.h>
|
||
|
||
using namespace std;
|
||
|
||
// class definitions
|
||
class Card
|
||
{
|
||
//
|
||
public:
|
||
Card(char value, char suit)
|
||
{
|
||
// store the value and suit. (possible values 2-9, T, J, Q, K, A)
|
||
cardValue = value;
|
||
cardSuit = suit;
|
||
// get the numerical value of the card, casting from string to num where possible. (2-9)
|
||
if((cardValue >= 2) || (cardValue <= 9))
|
||
{
|
||
// cast the character to number.
|
||
cardNumericalValue = (int)cardValue - 48; // numerical values 2-9 only
|
||
}
|
||
// face values here.
|
||
if(cardValue == 'T')
|
||
{
|
||
// 'ten' card
|
||
cardNumericalValue = 10;
|
||
}
|
||
if(cardValue == 'J')
|
||
{
|
||
// jack
|
||
cardNumericalValue = 11;
|
||
}
|
||
if(cardValue == 'Q')
|
||
{
|
||
// queen
|
||
cardNumericalValue = 12;
|
||
}
|
||
if(cardValue == 'K')
|
||
{
|
||
// king
|
||
cardNumericalValue = 13;
|
||
}
|
||
// special 1/Ace card here
|
||
if (cardValue == 'A')
|
||
{
|
||
cardNumericalValue = 1;
|
||
}
|
||
// add the cardValue and cardSuit to the string
|
||
fullCard = fullCard + cardValue;
|
||
fullCard = fullCard + cardSuit;
|
||
}
|
||
int getCardValue()
|
||
{
|
||
//
|
||
return cardNumericalValue;
|
||
}
|
||
char getCardRawValue()
|
||
{
|
||
//
|
||
return cardValue;
|
||
}
|
||
char getCardSuit()
|
||
{
|
||
//
|
||
return cardSuit;
|
||
}
|
||
string getFullCard()
|
||
{
|
||
return fullCard;
|
||
}
|
||
friend bool operator==(const Card &cardOne, const Card &cardTwo)
|
||
{
|
||
// compare cardOne's value to cardTwo's value.
|
||
// THIS WILL ONLY CHECK NUMERICAL VALUE
|
||
// If I was doing this for a REAL card game, I would add an
|
||
// && (cardOne.cardSuit == cardTwo.cardSuit)
|
||
// to make sure that the suit AND value are the same.
|
||
return (cardOne.cardNumericalValue == cardTwo.cardNumericalValue);
|
||
}
|
||
friend bool operator<(const Card &cardOne, const Card &cardTwo)
|
||
{
|
||
// compare cardOne's value to cardTwo's value with less than function.
|
||
// THIS WILL ONLY CHECK NUMERICAL VALUE
|
||
return (cardOne.cardNumericalValue < cardTwo.cardNumericalValue);
|
||
}
|
||
private:
|
||
char cardValue;
|
||
char cardSuit;
|
||
int cardNumericalValue;
|
||
string fullCard;
|
||
};
|
||
|
||
// function prototypes
|
||
int humanTurn(vector<Card> &human, vector<Card> &computer, vector<Card> &cardDeck);
|
||
int computerTurn(vector<Card> &human, vector<Card> &computer, vector<Card> &cardDeck);
|
||
|
||
// main program
|
||
int main(int argc, char **argv)
|
||
{
|
||
// create array of cards called deck.
|
||
vector<Card> deck;
|
||
// have two hands for cards
|
||
vector<Card> humanHand;
|
||
vector<Card> computerHand;
|
||
// keep count of the number of sets collected. ends when number is 13.
|
||
int currentNumSets = 0;
|
||
// char array for the setups
|
||
char suits[] = {'C','D','H','S'};
|
||
int suitsLen = sizeof(suits)/sizeof(suits[0]);
|
||
// char values[] = {'A','2','3','4','5','6','7','8','9','T','J','Q','K'};
|
||
char values[] = {'K','Q','J','T','9','8','7','6','5','4','3','2','A'};
|
||
int valuesLen = (sizeof(values)/sizeof(values[0]));
|
||
// game setup
|
||
// create deck by loop for 1 - 13 with each suit {(H)earts, S(pades), C(lubs), D(iamonds)}.
|
||
// use double for loop, outer for suits, inner for values.
|
||
for (int deckCounter = 0; deckCounter < suitsLen; deckCounter++)
|
||
{
|
||
// creates each suit
|
||
for (int suitCounter = 0; suitCounter < valuesLen; suitCounter++)
|
||
{
|
||
// creates each card/value
|
||
deck.push_back(Card(values[suitCounter], suits[deckCounter]));
|
||
}
|
||
}
|
||
// shuffle deck randomly? (use shuffle function from algorithm library)
|
||
// generate a random number (which is so much harder in CPP because they 'frown upon' using the C STL rand stuff)
|
||
default_random_engine randNumGen(time(NULL));
|
||
// shuffle the deck using that rng engine.
|
||
shuffle(deck.begin(), deck.end(), randNumGen);
|
||
// deal hands by taking each card from the deck, one by one (7x) (for loop here.)
|
||
for(int dealIterator = 0; dealIterator < 7; dealIterator++)
|
||
{
|
||
// grab the last card from the deck, put it in the human's hand
|
||
humanHand.push_back(deck.back());
|
||
deck.pop_back();
|
||
// grab the last card from the deck, put it in the computer's hand
|
||
computerHand.push_back(deck.back());
|
||
deck.pop_back();
|
||
}
|
||
// tell the user the game has started.
|
||
cout << "Game Start." << endl;
|
||
// output the human's hand to the screen
|
||
cout << "Here is your starting hand:" << endl << "| ";
|
||
int handSize = humanHand.size();
|
||
for(int handDisplayIterator = 0; handDisplayIterator < handSize; handDisplayIterator++)
|
||
{
|
||
cout << humanHand[handDisplayIterator].getFullCard() << " | ";
|
||
}
|
||
cout << endl;
|
||
// main gameplay loop (while?)
|
||
while(currentNumSets != 13)
|
||
{
|
||
// switch back and forth between human and computer.
|
||
currentNumSets = currentNumSets + humanTurn(humanHand, computerHand, deck);
|
||
currentNumSets = currentNumSets + computerTurn(humanHand, computerHand, deck);
|
||
}
|
||
// return 0
|
||
return 0;
|
||
}
|
||
|
||
/* THIS BELOW CODE IS FOR CHECKING THE DECK
|
||
for (int tempIterator = 0; tempIterator < 52; tempIterator++)
|
||
{
|
||
// print off each card to see if it was correctly made.
|
||
cout << tempIterator << ": " << deck[tempIterator].getFullCard() << " | ";
|
||
}
|
||
cout << endl;
|
||
*/
|
||
|
||
// compiles using "g++ -Wall -pedantic go_fish.cpp -o go_fish" - note to programmer
|
||
|
||
/*
|
||
Function Name: humanTurn
|
||
Process: ???
|
||
Function Input/Parameters: ???
|
||
Function Output/Parameters: ???
|
||
Function Output/Returned: ???
|
||
Device Input/Device: ???
|
||
Device Output/Monitor: ???
|
||
Dependencies: ???
|
||
*/
|
||
int humanTurn(vector<Card> &human, vector<Card> &computer, vector<Card> &cardDeck)
|
||
{
|
||
/*
|
||
Handles the human’s turn. It will prompt the player to ask for a card rank/number and
|
||
check if the computer has the requested rank/number. If the card is available in the
|
||
computer’s hand, it will transfer the card to the human’s hand otherwise, it will draw a
|
||
card. The function should return the number of sets collected during the turn
|
||
*/
|
||
|
||
int numSets = 0;
|
||
int maxCountCard = 0;
|
||
char inputChar;
|
||
bool foundCard = false;
|
||
// ask for card rank/number/value
|
||
cout << "Your turn. Ask for a card (2-9, J/Q/K/A): " << endl;
|
||
cin.ignore();
|
||
cout << ">";
|
||
cin >> inputChar;
|
||
Card valueOnlyCard(inputChar, 'X');
|
||
// if card is in opposite hand, remove from and give to the other. (loop through computer hand looking for card)
|
||
for(int checkHandIterator = 0; checkHandIterator < computer.size(); checkHandIterator++)
|
||
{
|
||
// checking if value of card is equal to any of the other ones.
|
||
if(computer[checkHandIterator].getCardRawValue() == inputChar)
|
||
{
|
||
// copy the card into the human's hand.
|
||
human.push_back(computer[checkHandIterator]);
|
||
// set the card find to true.
|
||
foundCard = true;
|
||
}
|
||
}
|
||
// remove the cards that had been drawn from the other hand (use remove/remove if and erase with the vector iterators)
|
||
// NOTE: https://stackoverflow.com/questions/72179264/classes-remove-a-specific-object-from-a-vector-of-objects
|
||
if(foundCard)
|
||
{
|
||
// remove cards if found
|
||
computer.erase(remove_if(computer.begin(), computer.end(), [&](Card &remCard){return remCard.getCardValue() == inputChar;}), computer.end());
|
||
}
|
||
// if not, draw a card from the top of the deck.
|
||
else
|
||
{
|
||
// draw a card if not found.
|
||
human.push_back(cardDeck.back());
|
||
cardDeck.pop_back();
|
||
}
|
||
// check to see if sets exist in the vector, aka is there four of a value.
|
||
// if there is four of a value, increase the number of sets to return, remove the cards from hand.
|
||
// NOTE: https://stackoverflow.com/questions/39906504/how-to-count-duplicates-in-a-vector-c
|
||
for (int setCounter = 0; setCounter < human.size(); setCounter++)
|
||
{
|
||
/* code */
|
||
}
|
||
|
||
|
||
// return the number of sets
|
||
return numSets;
|
||
}
|
||
|
||
/*
|
||
Function Name: computerTurn
|
||
Process: ???
|
||
Function Input/Parameters: ???
|
||
Function Output/Parameters: ???
|
||
Function Output/Returned: ???
|
||
Device Input/Device: ???
|
||
Device Output/Monitor: ???
|
||
Dependencies: ???
|
||
*/
|
||
int computerTurn(vector<Card> &human, vector<Card> &computer, vector<Card> &cardDeck)
|
||
{
|
||
/*
|
||
Handles the computer’s turn and it should do the same actions as the human but for the
|
||
computer. The function should return the number of set that is collected during its turn.
|
||
*/
|
||
// return the number of sets
|
||
return 0;
|
||
} |