Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

(C++) Understand the Class and Problem We endeavor to set up some classes that c

ID: 3856283 • Letter: #

Question

(C++)

Understand the Class and Problem

We endeavor to set up some classes that can be used in future programs that involve playing card games with a human or simulating card games entirely by a computer. There are two basic classes we'll need this week:

Card: A class like the one presented in the modules, but with a few changes.

Hand: A class that represents the cards held by a single player.

Notice that I am using the char 'T' to describe the value 10. (Ignore the Joker, which we will not need.)

The dealer uses a Deck object (not implemented this week) to deal Hand objects to the players. The dealer may or may not be a player who gets a hand of his own (poker dealers in casinos don't receive a hand, but most other games involve the dealer getting a hand).


Card: The Card class has two obvious members:  value (a char) and suit (anenum). But we add a new boolean, errorFlag, which can inform a client that a card is in an illegal state. We'll want the usual constructors, mutators, accessors and toString() methods for the class. We only allow standard cards, like ('A', clubs), ('9', hearts) and ('T', diamonds), no jokers or other special cards.

Hand: As you can see, a Hand object usually contains several cards, so we'll need an array of Cardobjects (myCards) as the principal member of the Hand class. Since each game deals a different number of cards into its players hands, and even within a game the number of cards in a hand will increase or decrease, we must keep track of this with an int value (numCards). We'll need constructors, mutators, etc., of course. We'll also want a way for the hand to receive a card (from the deck or somewhere else), and play a card (to the table or to another player). These two methods will be called takeCard() and playCard(), respectively. Since this class has no information about the game being played, it always puts new cards received by takeCard() into the next available location of the array (index position numCards) and plays a card via playCard() from the highest occupied location (index position numCards - 1). The client game application would somehow prepare this highest position with the correct card to be played before calling Hand's playCard() method. This detail is not our concern.

Phase 1: The Card Class

A Public enum Type

Define the Suit enum, { clubs, diamonds, hearts, spades }, inside the Card class.

Private Member Data

Include three members:

Public Methods

Card(char value, Suit suit) - The constructor should call the proper mutator(s). Overload this to cope with a client that wants to instantiate without parameters and use 'A' and 'spades' as the default value and suit when not supplied. Provide at least two constructors -- no parameters andall parameters -- or more if you wish. Because we have the errorFlagmember, the constuctor (via the mutator), can set that member when it gets bad data; it does not have to assign default values upon receipt of bad data. This is a new technique for us. Again, default card (no parameters passed) is the ('A', spades).

String toString() - a stringizer that the client can use prior to displaying the card. It provides a clean representation of the card. If errorFlag == true, it should return correspondingly reasonable reflection of this fact (something like "[ invalid ]" rather than a suit and value).

boolean set(char value, Suit suit) - a mutator that accepts the legal values established in the earlier section. When bad values are passed, errorFlag is set to true and other values can be left in any state (even partially set). If good values are passed, they are stored and errorFlag is set to false. Make use of the private helper, listed below.

No mutator for errorFlag - that would not make sense.

Accessors for suit, value and errorFlag.

boolean equals(Card card) - returns true if all the fields (members) are identical and false, otherwise.

Private Methods

boolean static isValid(char value, Suit suit) - a static helper method that returns true or false, depending on the legality of the parameters. Note that, although it may be impossible for suit to be illegal (due to its enum-ness), we pass it, anyway, in anticipation of possible changes to the type from enum to, say, char or int, someday. We only need to test value, at this time.

Note: we don't need individual mutators for value or suit since they would not be needed for this particular class.

Recommended test of Card class

Instantiate three cards. Instantiate two legally and a third illegally. Use one default constructor and the others parameter-taking constructors. Print all three out and confirm. Then make good card bad by set() with an illegal value, and turn the a card "good" by setting a legal value.

Phase 2: The Hand Class

Static Class Constants

Define a public int value like MAX_CARDS and set it to something like 30 or 50 so a runaway program can't try to create a monster array.

Private Member Data

Public Methods

Hand() - a default constructor.

void resetHand() - remove all cards from the hand (in the simplest way).

boolean takeCard(Card card) - adds a card to the next available position in the myCards array if the parameter is an error-free Card object and if there is room in the Hand object for another card (according to MAX_CARDS). It returns false if the Hand was full, and true otherwise, even if card was an invalid (error-containing) card. So, if card is invalid but there would have been room for it, the method will return true, even though it did not add card to the hand. This is an object copy, not a reference copy, since the source of theCard might destroy or change its data after our Handgets it -- we want our local data to be exactly as it was when we received it.

Card playCard() - returns and removes (effectively, not physically) the card in the top occupied position of the array.

String toString() - a stringizer that the client can use prior to displaying the entire hand.

Accessor for numCards.

Card inspectCard(int k) - Accessor for an individual card. Returns a card witherrorFlag = true if kis bad.

Recommended test of Hand class

Create between two and five explicit Card objects and one Hand object. UsetakeCard() on these few cards (resulting in many, unavoidable "duplicates" in the hand) in a loop to populate the hand until the maximum allowable cards is met (use this criterion to end the loop). Display the hand using toString(). Next,  playeach card in a loop, until the hand is empty. Display the card played as it is played, and finally, display the (now empty)  hand, verifying that no cards remain. At some point in your program, test inspectCard() with both legal and illegal int arguments.

Example Test Run of Hand Class

Your Clients and Runs

Since there are two phases, you'll want to have two different test main()s (or else one larger test main()that has two unrelated parts, phase 1 followed by phase 2). So supply both main()s and label which is which (phase 1 or phase 2) and two runs, or one large run clearly labeling the separation between phase 1 andphase 2.

c dr ICYCL Qr JOKER

Explanation / Answer

#ifndef CARD_H
#define CARD_H

#include <string>

const int SUIT_MAX(4);
const int RANK_MAX(13);

class Card
{
friend class Deck; // Deck Class needs to access to Card Class but not vice versa
public:
explicit Card();
explicit Card(const int &suit, const int &rank);

std::string Card2Str() const;

private:
int generate_suit();
int generate_rank();
int get_suit() const;
int get_rank() const;
int m_suit;
int m_rank;
};
#endif

OR
#include <stdlib.h> /* srand, rand */
#include "card.h"
#include <iostream>


const std::string SUIT[SUIT_MAX] = {"S", "H", "D", "C"};
const std::string RANK[RANK_MAX] = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};


Card::Card()
{
m_suit = generate_suit();
m_rank = generate_rank();
}

Card::Card(const int &suit, const int &rank) : m_suit(suit), m_rank(rank)
{

}

int Card::generate_suit()
{
return rand() % (SUIT_MAX-1) + 0;
}

int Card::generate_rank()
{
return rand() % (RANK_MAX-1) + 0;
}

std::string Card::Card2Str() const
{
return SUIT[get_suit()] + RANK[get_rank()];
}

int Card::get_suit() const
{
return m_suit;
}

int Card::get_rank() const
{
return m_rank;
}
OR
#ifndef DECK_H
#define DECK_H

#include <vector>
#include <iostream>
#include <fstream>
#include "card.h"

using namespace std;

class Deck
{
public:
explicit Deck();
void print_Deck() const;
void getOneCard();
private:
std::vector<Card> m_deck;

};

#endif

#include <iostream>
#include "deck.h"


Deck::Deck()
{
for (unsigned int i(0); i < SUIT_MAX; ++i)
{
for (unsigned int j(0); j < RANK_MAX; ++j)
{
Card card(i, j);
m_deck.push_back(card);
}
}
}


void Deck::print_Deck() const
{
unsigned int count(1);

for (unsigned int i(0); i < m_deck.size(); ++i)
{
std::cout << m_deck[i].Card2Str() << " ";
if ( count == 13 )
{
std::cout << std::endl;
count = 0;
}
++count;
}
}

void Deck::getOneCard()
{   
Card cd(m_deck.back().get_suit(), m_deck.back().get_rank());
m_deck.pop_back();
std::cout << cd.Card2Str() << std::endl;
}
main.cpp

#include <iostream>
#include <vector>
#include <stdlib.h>   
#include <time.h>   
#include <string>

#include "card.h"
#include "deck.h"

int main()
{
srand (time(NULL));

Deck _deck;
_deck.print_Deck();
_deck.getOneCard();

std::cout << std::endl;
_deck.print_Deck();


std::cout << std::endl;

return 0;
}


OR


public class Card {

public final static int SPADES = 0;   
public final static int HEARTS = 1;
public final static int DIAMONDS = 2;
public final static int CLUBS = 3;
public final static int JOKER = 4;

public final static int ACE = 1;
public final static int JACK = 11;
public final static int QUEEN = 12;   
public final static int KING = 13;


private final int suit;

private final int value;

  
public Card() {
suit = JOKER;
value = 1;
}


public Card(int theValue, int theSuit) {
if (theSuit != SPADES && theSuit != HEARTS && theSuit != DIAMONDS &&
theSuit != CLUBS && theSuit != JOKER)
throw new IllegalArgumentException("Illegal playing card suit");
if (theSuit != JOKER && (theValue < 1 || theValue > 13))
throw new IllegalArgumentException("Illegal playing card value");
value = theValue;
suit = theSuit;
}

  
public int getSuit() {
return suit;
}

public int getValue() {
return value;
}


public String getSuitAsString() {
switch ( suit ) {
case SPADES: return "Spades";
case HEARTS: return "Hearts";
case DIAMONDS: return "Diamonds";
case CLUBS: return "Clubs";
default: return "Joker";
}
}


public String getValueAsString() {
if (suit == JOKER)
return "" + value;
else {
switch ( value ) {
case 1: return "Ace";
case 2: return "2";
case 3: return "3";
case 4: return "4";
case 5: return "5";
case 6: return "6";
case 7: return "7";
case 8: return "8";
case 9: return "9";
case 10: return "10";
case 11: return "Jack";
case 12: return "Queen";
default: return "King";
}
}
}

  
public String toString() {
if (suit == JOKER) {
if (value == 1)
return "Joker";
else
return "Joker #" + value;
}
else
return getValueAsString() + " of " + getSuitAsString();
}

} // end class Card

public class HighLow {


public static void main(String[] args) {

System.out.println("This program lets you play the simple card game,");
System.out.println("HighLow. A card is dealt from a deck of cards.");
System.out.println("You have to predict whether the next card will be");
System.out.println("higher or lower. Your score in the game is the");
System.out.println("number of correct predictions you make before");
System.out.println("you guess wrong.");
System.out.println();
  
int gamesPlayed = 0;   
int sumOfScores = 0;

double averageScore;   

boolean playAgain;   


  
do {
int scoreThisGame;
scoreThisGame = play();   
sumOfScores += scoreThisGame;
gamesPlayed++;
System.out.print("Play again? ");
playAgain = TextIO.getlnBoolean();
} while (playAgain);
  
averageScore = ((double)sumOfScores) / gamesPlayed;
  
System.out.println();
System.out.println("You played " + gamesPlayed + " games.");
System.out.printf("Your average score was %1.3f. ", averageScore);

} // end main()


private static int play() {

Deck deck = new Deck();
  
Card currentCard;

Card nextCard;   

int correctGuesses ;
  
  

char guess;   
  
  
  
deck.shuffle();

correctGuesses = 0;
currentCard = deck.dealCard();
System.out.println("The first card is the " + currentCard);
  
while (true) {

/* Get the user's prediction, 'H' or 'L' (or 'h' or 'l'). */

System.out.print("Will the next card be higher (H) or lower (L)? ");
do {
guess = TextIO.getlnChar();
guess = Character.toUpperCase(guess);
if (guess != 'H' && guess != 'L')
System.out.print("Please respond with H or L: ");
} while (guess != 'H' && guess != 'L');

/* Get the next card and show it to the user. */

nextCard = deck.dealCard();
System.out.println("The next card is " + nextCard);

/* Check the user's prediction. */

if (nextCard.getValue() == currentCard.getValue()) {
System.out.println("The value is the same as the previous card.");
System.out.println("You lose on ties. Sorry!");
break; // End the game.
}
else if (nextCard.getValue() > currentCard.getValue()) {
if (guess == 'H') {
System.out.println("Your prediction was correct.");
correctGuesses++;
}
else {
System.out.println("Your prediction was incorrect.");
break; // End the game.
}
}
else { // nextCard is lower
if (guess == 'L') {
System.out.println("Your prediction was correct.");
correctGuesses++;
}
else {
System.out.println("Your prediction was incorrect.");
break; // End the game.
}
}



currentCard = nextCard;
System.out.println();
System.out.println("The card is " + currentCard);

} // end of while loop
  
System.out.println();
System.out.println("The game is over.");
System.out.println("You made " + correctGuesses
+ " correct predictions.");
System.out.println();
  
return correctGuesses;
  
} // end play()

} // end class HighLow