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'],
|
['src/chapter_4/lab_4/main.cpp', 'src/chapter_4/lab_4/Distance.cpp'],
|
||||||
install: true,
|
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