feat: finish chapter 4 program 3
This commit is contained in:
parent
61c0b4fce9
commit
d40127ed66
7 changed files with 306 additions and 0 deletions
10
meson.build
10
meson.build
|
@ -28,3 +28,13 @@ c_4_lab_4 = executable(
|
|||
['src/chapter_4/lab_4/main.cpp', 'src/chapter_4/lab_4/Distance.cpp'],
|
||||
install: true,
|
||||
)
|
||||
|
||||
c_4_program_3 = executable(
|
||||
'c_4_program_3',
|
||||
[
|
||||
'src/chapter_4/program_3/main.cpp',
|
||||
'src/chapter_4/program_3/Card.cpp',
|
||||
'src/chapter_4/program_3/Deck.cpp',
|
||||
],
|
||||
install: true,
|
||||
)
|
||||
|
|
65
src/chapter_4/program_3/Card.cpp
Normal file
65
src/chapter_4/program_3/Card.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
#include "Card.h"
|
||||
|
||||
Card::Card() {
|
||||
suit = 'c';
|
||||
rank = 2;
|
||||
}
|
||||
|
||||
Card::Card(char suit, int rank) {
|
||||
char suit_lowered = tolower(suit);
|
||||
if (suit_lowered != 'c' && suit_lowered != 'h' && suit_lowered != 's' &&
|
||||
suit_lowered != 'd') {
|
||||
this->suit = 'c';
|
||||
} else {
|
||||
this->suit = suit_lowered;
|
||||
}
|
||||
if (rank < 0 || rank > 13) {
|
||||
this->rank = 2;
|
||||
} else {
|
||||
this->rank = rank;
|
||||
}
|
||||
}
|
||||
|
||||
char Card::getSuit() const { return this->suit; }
|
||||
int Card::getRank() const { return this->rank; }
|
||||
|
||||
ostream &operator<<(ostream &stream, const Card &card) {
|
||||
string suitName;
|
||||
string cardName;
|
||||
|
||||
switch (card.suit) {
|
||||
case 'c':
|
||||
suitName = "Clubs";
|
||||
break;
|
||||
case 'd':
|
||||
suitName = "Diamonds";
|
||||
break;
|
||||
case 'h':
|
||||
suitName = "Hearts";
|
||||
break;
|
||||
case 's':
|
||||
suitName = "Spades";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (card.rank) {
|
||||
case 1:
|
||||
cardName = "Ace";
|
||||
break;
|
||||
case 11:
|
||||
cardName = "Jack";
|
||||
break;
|
||||
case 12:
|
||||
cardName = "Queen";
|
||||
break;
|
||||
case 13:
|
||||
cardName = "King";
|
||||
break;
|
||||
default:
|
||||
cardName = to_string(card.rank);
|
||||
}
|
||||
|
||||
stream << cardName << " of " << suitName;
|
||||
|
||||
return stream;
|
||||
}
|
48
src/chapter_4/program_3/Card.h
Normal file
48
src/chapter_4/program_3/Card.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
//Card interface file
|
||||
#ifndef __CARD_H__
|
||||
#define __CARD_H__
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Card {
|
||||
private:
|
||||
char suit;
|
||||
int rank;
|
||||
public:
|
||||
|
||||
/* Assigns a default value of 2 of Clubs
|
||||
*/
|
||||
Card();
|
||||
|
||||
|
||||
/* Assigns the Card the suit and rank provided.
|
||||
suits: c = Clubs, d = Diamonds, h = Hearts, s = Spades
|
||||
If an invalid suit is provided, sets the suit to Clubs
|
||||
ranks: 1 - 13 (1 = Ace, 11 = Jack, 12 = Queen, 13 = King)
|
||||
If an invalid rank is provided, sets the rank to 2
|
||||
Accepts lower or upper case characters for suit
|
||||
*/
|
||||
Card(char, int);
|
||||
|
||||
|
||||
/* Returns the Card's suit
|
||||
*/
|
||||
char getSuit() const;
|
||||
|
||||
|
||||
/* Returns the Card's rank as an integer
|
||||
*/
|
||||
int getRank() const;
|
||||
|
||||
/* Outputs a Card in the following format: Rank of Suit
|
||||
For example, if the rank is 3 and the suit is h: 3 of Hearts
|
||||
Or, if the rank is 1 and the suit is d: Ace of Diamonds
|
||||
Or, if the rank is 12 and the suit is c: Queen of Clubs
|
||||
etc.
|
||||
*/
|
||||
friend ostream & operator<<(ostream &, const Card &);
|
||||
};
|
||||
|
||||
#endif
|
29
src/chapter_4/program_3/Deck.cpp
Normal file
29
src/chapter_4/program_3/Deck.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include "Deck.h"
|
||||
#include <algorithm>
|
||||
|
||||
Deck::Deck() {
|
||||
char suits[] = {'s', 'h', 'd', 'c'};
|
||||
|
||||
for (char c : suits) {
|
||||
for (int i = 13; i >= 1; i--) {
|
||||
theDeck.push_back(Card(c, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Deck::shuffleDeck() {
|
||||
for (auto c : dealtCards) {
|
||||
theDeck.push_back(c);
|
||||
}
|
||||
dealtCards.clear();
|
||||
random_shuffle(theDeck.begin(), theDeck.end());
|
||||
}
|
||||
|
||||
unsigned Deck::deckSize() const { return theDeck.size(); }
|
||||
|
||||
Card Deck::dealCard() {
|
||||
Card back = theDeck.back();
|
||||
dealtCards.push_back(back);
|
||||
theDeck.pop_back();
|
||||
return back;
|
||||
}
|
50
src/chapter_4/program_3/Deck.h
Normal file
50
src/chapter_4/program_3/Deck.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#ifndef __DECK_H__
|
||||
#define __DECK_H__
|
||||
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
#include "Card.h"
|
||||
|
||||
class Deck {
|
||||
private:
|
||||
vector<Card> theDeck;
|
||||
vector<Card> dealtCards;
|
||||
public:
|
||||
/* Constructs a Deck of 52 cards:
|
||||
Ace, 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King of each suit.
|
||||
Cards should start off in this order with the order of suits being:
|
||||
Clubs, Diamonds, Hearts, Spades. So, the Card at the top of the
|
||||
Deck should be the Ace of Clubs. The next Card should be 2 of Clubs.
|
||||
The 3rd Card should be 3 of Clubs, and so on ...
|
||||
|
||||
For best efficiency, the top of Deck should be stored at
|
||||
back end of vector.
|
||||
*/
|
||||
Deck();
|
||||
|
||||
/* Deals (returns) the top card of the deck.
|
||||
Removes this card from theDeck and places it in dealtCards.
|
||||
As mentioned in comments for the constructor,
|
||||
for best efficiency, the top card should come from the
|
||||
back end of vector.
|
||||
*/
|
||||
Card dealCard();
|
||||
|
||||
|
||||
/* Places all cards back into theDeck and shuffles them into random order.
|
||||
Use random_shuffle function from algorithm library.
|
||||
To pass test harness, this function must go forward through dealtCards
|
||||
pushing each Card onto the back end of theDeck, then clear dealtCards.
|
||||
Do not use pop_back on dealtCards.
|
||||
*/
|
||||
void shuffleDeck();
|
||||
|
||||
|
||||
/* returns the size of the Deck (how many cards have not yet been dealt).
|
||||
*/
|
||||
unsigned deckSize() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
6
src/chapter_4/program_3/hands.dat
Normal file
6
src/chapter_4/program_3/hands.dat
Normal file
|
@ -0,0 +1,6 @@
|
|||
Found Pair!! Ace of Hearts, 8 of Diamonds, 9 of Hearts, 3 of Hearts, 9 of Spades, 5 of Spades, 10 of Diamonds, 9 of Diamonds, Queen of Spades, 8 of Spades,
|
||||
Found Pair!! 5 of Clubs, 9 of Hearts, 3 of Spades, 2 of Spades, King of Spades, 2 of Clubs, King of Diamonds, Jack of Spades, Jack of Diamonds, 5 of Diamonds,
|
||||
Found Pair!! 3 of Spades, Jack of Diamonds, 9 of Spades, 4 of Spades, 10 of Clubs, 7 of Spades, 9 of Diamonds, 7 of Hearts, Ace of Clubs, 4 of Diamonds,
|
||||
Found Pair!! Ace of Clubs, 9 of Hearts, 6 of Spades, 9 of Spades, 2 of Hearts, Queen of Diamonds, 4 of Spades, Jack of Spades, 8 of Diamonds, 5 of Clubs,
|
||||
Found Pair!! 3 of Clubs, Ace of Spades, 6 of Hearts, 5 of Clubs, 7 of Clubs, King of Spades, 10 of Spades, Queen of Hearts, King of Clubs, Jack of Diamonds,
|
||||
|
98
src/chapter_4/program_3/main.cpp
Normal file
98
src/chapter_4/program_3/main.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "Card.h"
|
||||
#include "Deck.h"
|
||||
|
||||
// Returns true if vector of Cards passed in contains at least 2 Cards with the
|
||||
// same rank.
|
||||
bool hasPair(const vector<Card>);
|
||||
double simulateMonteCarlo(Deck, int, int, bool, ostream &);
|
||||
|
||||
// Sends to output stream a hand of Cards on a single line,
|
||||
// each Card separated by a comma.
|
||||
// If the vector is empty, do not output anything.
|
||||
// Example (vector size of 3): Ace of Spades, Two of Hearts, King of Clubs
|
||||
ostream &operator<<(ostream &, const vector<Card> &);
|
||||
|
||||
int main() {
|
||||
srand(2222);
|
||||
bool toFile;
|
||||
int numOfHands;
|
||||
int numOfDeals;
|
||||
string filename;
|
||||
string in;
|
||||
fstream file;
|
||||
|
||||
cout << "Do you want to output all hands to a file?(Yes/No)";
|
||||
|
||||
cin >> in;
|
||||
toFile = in == "Yes";
|
||||
if (toFile) {
|
||||
cout << endl << "Enter name of output file: ";
|
||||
cin >> filename;
|
||||
file.open(filename, fstream::out);
|
||||
};
|
||||
cout << endl << "Enter number of cards per hand: ";
|
||||
cin >> numOfHands;
|
||||
cout << endl << "Enter number of deals (simulations): ";
|
||||
cin >> numOfDeals;
|
||||
|
||||
double probability =
|
||||
simulateMonteCarlo(Deck(), numOfHands, numOfDeals, toFile, file);
|
||||
|
||||
cout << endl
|
||||
<< "Chances of receiving a pair in a hand of " << numOfHands
|
||||
<< " cards is: " << (probability * 100) << '%' << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
double simulateMonteCarlo(Deck deck, int numOfHands, int numOfDeals,
|
||||
bool shouldStreamOutput, ostream &stream) {
|
||||
int pairCount = 0;
|
||||
vector<Card> hand;
|
||||
for (int i = 0; i < numOfDeals; i++) {
|
||||
deck.shuffleDeck();
|
||||
for (int j = 0; j < numOfHands; j++) {
|
||||
hand.push_back(deck.dealCard());
|
||||
}
|
||||
if (hasPair(hand)) {
|
||||
pairCount++;
|
||||
if (shouldStreamOutput) {
|
||||
stream << "Found Pair!! ";
|
||||
}
|
||||
} else {
|
||||
if (shouldStreamOutput) {
|
||||
stream << " ";
|
||||
}
|
||||
}
|
||||
if (shouldStreamOutput) {
|
||||
for (unsigned int i = 0; i < hand.size(); i++) {
|
||||
stream << hand.at(i);
|
||||
if (i < hand.size() - 1) {
|
||||
stream << ", ";
|
||||
}
|
||||
}
|
||||
stream << endl;
|
||||
}
|
||||
hand.clear();
|
||||
}
|
||||
|
||||
return static_cast<double>(pairCount) / static_cast<double>(numOfDeals);
|
||||
}
|
||||
|
||||
bool hasPair(const vector<Card> vec) {
|
||||
for (unsigned int i = 0; i < vec.size() - 1; i++) {
|
||||
for (unsigned int j = i + 1; j < vec.size(); j++) {
|
||||
if (vec.at(i).getRank() == vec.at(j).getRank()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
Loading…
Reference in a new issue