1177 lines
41 KiB
C++
1177 lines
41 KiB
C++
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
* Champlain College SDEV-345-81
|
||
*
|
||
* C++ Week 4: Discussion (first semester) - Go Fish (2020/09/20)
|
||
*
|
||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
*
|
||
* Collaborate on the discussion to develop a card game. “Go Fish” is a classic children’s card game
|
||
*
|
||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
*
|
||
* Written by Llewellyn van der Merwe <llewellyn.vandermerw@mymail.champlain.edu>, September 2020
|
||
* Copyright (C) 2020. All Rights Reserved
|
||
* License GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html
|
||
*
|
||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||
|
||
#include <iostream>
|
||
#include <string>
|
||
#include <vector>
|
||
#include <map>
|
||
#include <stack>
|
||
#include <algorithm>
|
||
#include <random>
|
||
|
||
using namespace std;
|
||
|
||
class cardDB {
|
||
protected:
|
||
|
||
/**
|
||
* The Mapper of Specifics
|
||
**/
|
||
map<string, double> deck_specifics_a;
|
||
|
||
/**
|
||
* The Mapper for Reverse Specifics
|
||
**/
|
||
map<double, string> deck_specifics_b;
|
||
|
||
/**
|
||
* The Mapper for Ranks
|
||
**/
|
||
map<string, int> deck_ranks_a;
|
||
|
||
/**
|
||
* The Mapper for Reverse Ranks
|
||
**/
|
||
map<int, string> deck_ranks_b;
|
||
|
||
/**
|
||
* The Mapper for Display
|
||
**/
|
||
map<string, string> deck_display;
|
||
|
||
public:
|
||
/**
|
||
* for debugging
|
||
**/
|
||
bool debug = true;
|
||
// just change this to true to see debug info
|
||
|
||
/**
|
||
* Constructor to setup the mapper
|
||
**/
|
||
cardDB() {
|
||
// for display
|
||
this->deck_display["H1"] = "Ace of Hearts";
|
||
this->deck_display["D1"] = "Ace of Diamonds";
|
||
this->deck_display["S1"] = "Ace of Spades";
|
||
this->deck_display["C1"] = "Ace of Clubs";
|
||
|
||
this->deck_display["H2"] = "Two of Hearts";
|
||
this->deck_display["D2"] = "Two of Diamonds";
|
||
this->deck_display["S2"] = "Two of Spades";
|
||
this->deck_display["C2"] = "Two of Clubs";
|
||
|
||
this->deck_display["H3"] = "Three of Hearts";
|
||
this->deck_display["D3"] = "Three of Diamonds";
|
||
this->deck_display["S3"] = "Three of Spades";
|
||
this->deck_display["C3"] = "Three of Clubs";
|
||
|
||
this->deck_display["H4"] = "Four of Hearts";
|
||
this->deck_display["D4"] = "Four of Diamonds";
|
||
this->deck_display["S4"] = "Four of Spades";
|
||
this->deck_display["C4"] = "Four of Clubs";
|
||
|
||
this->deck_display["H5"] = "Five of Hearts";
|
||
this->deck_display["D5"] = "Five of Diamonds";
|
||
this->deck_display["S5"] = "Five of Spades";
|
||
this->deck_display["C5"] = "Five of Clubs";
|
||
|
||
this->deck_display["H6"] = "Six of Hearts";
|
||
this->deck_display["D6"] = "Six of Diamonds";
|
||
this->deck_display["S6"] = "Six of Spades";
|
||
this->deck_display["C6"] = "Six of Clubs";
|
||
|
||
this->deck_display["H7"] = "Seven of Hearts";
|
||
this->deck_display["D7"] = "Seven of Diamonds";
|
||
this->deck_display["S7"] = "Seven of Spades";
|
||
this->deck_display["C7"] = "Seven of Clubs";
|
||
|
||
this->deck_display["H8"] = "Eight of Hearts";
|
||
this->deck_display["D8"] = "Eight of Diamonds";
|
||
this->deck_display["S8"] = "Eight of Spades";
|
||
this->deck_display["C8"] = "Eight of Clubs";
|
||
|
||
this->deck_display["H9"] = "Nine of Hearts";
|
||
this->deck_display["D9"] = "Nine of Diamonds";
|
||
this->deck_display["S9"] = "Nine of Spades";
|
||
this->deck_display["C9"] = "Nine of Clubs";
|
||
|
||
this->deck_display["H10"] = "Ten of Hearts";
|
||
this->deck_display["D10"] = "Ten of Diamonds";
|
||
this->deck_display["S10"] = "Ten of Spades";
|
||
this->deck_display["C10"] = "Ten of Clubs";
|
||
|
||
this->deck_display["HJ"] = "Jack of Hearts";
|
||
this->deck_display["DJ"] = "Jack of Diamonds";
|
||
this->deck_display["SJ"] = "Jack of Spades";
|
||
this->deck_display["CJ"] = "Jack of Clubs";
|
||
|
||
this->deck_display["HQ"] = "Queen of Hearts";
|
||
this->deck_display["DQ"] = "Queen of Diamonds";
|
||
this->deck_display["SQ"] = "Queen of Spades";
|
||
this->deck_display["CQ"] = "Queen of Clubs";
|
||
|
||
this->deck_display["HK"] = "King of Hearts";
|
||
this->deck_display["DK"] = "King of Diamonds";
|
||
this->deck_display["SK"] = "King of Spades";
|
||
this->deck_display["CK"] = "King of Clubs";
|
||
|
||
this->deck_specifics_a["H1"] = 1.1; // Ace of Hearts
|
||
this->deck_specifics_a["D1"] = 1.2; // Ace of Diamonds
|
||
this->deck_specifics_a["S1"] = 1.3; // Ace of Spades
|
||
this->deck_specifics_a["C1"] = 1.4; // Ace of Clubs
|
||
|
||
this->deck_specifics_a["H2"] = 2.1; // Two of Hearts
|
||
this->deck_specifics_a["D2"] = 2.2; // Two of Diamonds
|
||
this->deck_specifics_a["S2"] = 2.3; // Two of Spades
|
||
this->deck_specifics_a["C2"] = 2.4; // Two of Clubs
|
||
|
||
this->deck_specifics_a["H3"] = 3.1; // Three of Hearts
|
||
this->deck_specifics_a["D3"] = 3.2; // Three of Diamonds
|
||
this->deck_specifics_a["S3"] = 3.3; // Three of Spades
|
||
this->deck_specifics_a["C3"] = 3.4; // Three of Clubs
|
||
|
||
this->deck_specifics_a["H4"] = 4.1; // Four of Hearts
|
||
this->deck_specifics_a["D4"] = 4.2; // Four of Diamonds
|
||
this->deck_specifics_a["S4"] = 4.3; // Four of Spades
|
||
this->deck_specifics_a["C4"] = 4.4; // Four of Clubs
|
||
|
||
this->deck_specifics_a["H5"] = 5.1; // Five of Hearts
|
||
this->deck_specifics_a["D5"] = 5.2; // Five of Diamonds
|
||
this->deck_specifics_a["S5"] = 5.3; // Five of Spades
|
||
this->deck_specifics_a["C5"] = 5.4; // Five of Clubs
|
||
|
||
this->deck_specifics_a["H6"] = 6.1; // Six of Hearts
|
||
this->deck_specifics_a["D6"] = 6.2; // Six of Diamonds
|
||
this->deck_specifics_a["S6"] = 6.3; // Six of Spades
|
||
this->deck_specifics_a["C6"] = 6.4; // Six of Clubs
|
||
|
||
this->deck_specifics_a["H7"] = 7.1; // Seven of Hearts
|
||
this->deck_specifics_a["D7"] = 7.2; // Seven of Diamonds
|
||
this->deck_specifics_a["S7"] = 7.3; // Seven of Spades
|
||
this->deck_specifics_a["C7"] = 7.4; // Seven of Clubs
|
||
|
||
this->deck_specifics_a["H8"] = 8.1; // Eight of Hearts
|
||
this->deck_specifics_a["D8"] = 8.2; // Eight of Diamonds
|
||
this->deck_specifics_a["S8"] = 8.3; // Eight of Spades
|
||
this->deck_specifics_a["C8"] = 8.4; // Eight of Clubs
|
||
|
||
this->deck_specifics_a["H9"] = 9.1; // Nine of Hearts
|
||
this->deck_specifics_a["D9"] = 9.2; // Nine of Diamonds
|
||
this->deck_specifics_a["S9"] = 9.3; // Nine of Spades
|
||
this->deck_specifics_a["C9"] = 9.4; // Nine of Clubs
|
||
|
||
this->deck_specifics_a["H10"] = 10.1; // Ten of Hearts
|
||
this->deck_specifics_a["D10"] = 10.2; // Ten of Diamonds
|
||
this->deck_specifics_a["S10"] = 10.3; // Ten of Spades
|
||
this->deck_specifics_a["C10"] = 10.4; // Ten of Clubs
|
||
|
||
this->deck_specifics_a["HJ"] = 11.1; // Jack of Hearts
|
||
this->deck_specifics_a["DJ"] = 11.2; // Jack of Diamonds
|
||
this->deck_specifics_a["SJ"] = 11.3; // Jack of Spades
|
||
this->deck_specifics_a["CJ"] = 11.4; // Jack of Clubs
|
||
|
||
this->deck_specifics_a["HQ"] = 12.1; // Queen of Hearts
|
||
this->deck_specifics_a["DQ"] = 12.2; // Queen of Diamonds
|
||
this->deck_specifics_a["SQ"] = 12.3; // Queen of Spades
|
||
this->deck_specifics_a["CQ"] = 12.4; // Queen of Clubs
|
||
|
||
this->deck_specifics_a["HK"] = 13.1; // King of Hearts
|
||
this->deck_specifics_a["DK"] = 13.2; // King of Diamonds
|
||
this->deck_specifics_a["SK"] = 13.3; // King of Spades
|
||
this->deck_specifics_a["CK"] = 13.4; // King of Clubs
|
||
|
||
// setup the reverse map
|
||
for (map<string, double>::iterator i = this->deck_specifics_a.begin(); i != this->deck_specifics_a.end(); ++i) {
|
||
this->deck_specifics_b[i->second] = i->first;
|
||
}
|
||
|
||
// set the deck ranks
|
||
this->deck_ranks_a["1"] = 1; // Ace
|
||
this->deck_ranks_a["2"] = 2; // Two
|
||
this->deck_ranks_a["3"] = 3; // Three
|
||
this->deck_ranks_a["4"] = 4; // Four
|
||
this->deck_ranks_a["5"] = 5; // Five
|
||
this->deck_ranks_a["6"] = 6; // Six
|
||
this->deck_ranks_a["7"] = 7; // Seven
|
||
this->deck_ranks_a["8"] = 8; // Eight
|
||
this->deck_ranks_a["9"] = 9; // Nine
|
||
this->deck_ranks_a["10"] = 10; // Ten
|
||
this->deck_ranks_a["J"] = 11; // Jack
|
||
this->deck_ranks_a["Q"] = 12; // Queen
|
||
this->deck_ranks_a["K"] = 13; // King
|
||
|
||
// setup the reverse map
|
||
for (map<string, int>::iterator i = this->deck_ranks_a.begin(); i != this->deck_ranks_a.end(); ++i) {
|
||
this->deck_ranks_b[i->second] = i->first;
|
||
}
|
||
}
|
||
|
||
// get the double KEY
|
||
double getDoubleKey(int rank, int shape) {
|
||
return (double) rank + ((double) shape / 10.0f);
|
||
}
|
||
|
||
// check if we can find the card
|
||
bool searchDeck(string key) {
|
||
// the iterator search
|
||
map<string, double>::iterator found = this->deck_specifics_a.find(key);
|
||
// check if it is found
|
||
if (found != this->deck_specifics_a.end()) {
|
||
// element found;
|
||
return true;
|
||
}
|
||
// the iterator search
|
||
map<string, int>::iterator rfound = this->deck_ranks_a.find(key);
|
||
// check if it is found
|
||
if (rfound != this->deck_ranks_a.end()) {
|
||
// element found;
|
||
return true;
|
||
}
|
||
// element not found
|
||
return false;
|
||
}
|
||
|
||
// check if we can find the card
|
||
bool searchDeck(double key) {
|
||
// the iterator search
|
||
map<double, string>::iterator found = this->deck_specifics_b.find(key);
|
||
// check if it is found
|
||
if (found != this->deck_specifics_b.end()) {
|
||
// element found;
|
||
return true;
|
||
}
|
||
// element not found
|
||
return false;
|
||
}
|
||
|
||
// get the card
|
||
double get(string key) {
|
||
// the iterator search
|
||
map<string, double>::iterator found = this->deck_specifics_a.find(key);
|
||
// check if it is found
|
||
if (found != this->deck_specifics_a.end()) {
|
||
// element found;
|
||
return found->second;
|
||
}
|
||
// element not found
|
||
return 0;
|
||
}
|
||
};
|
||
|
||
class deck : public cardDB {
|
||
protected:
|
||
/**
|
||
* mode 1 = RANK; 2 = SPECIFIC;
|
||
**/
|
||
int mode = 1; // default is RANK
|
||
|
||
/**
|
||
* To Shuffle Deck
|
||
*/
|
||
stack<double> deck_1;
|
||
stack<double> deck_2;
|
||
stack<double> deck_3;
|
||
stack<double> deck_4;
|
||
stack<double> deck_5;
|
||
|
||
public:
|
||
/**
|
||
* The Deck
|
||
**/
|
||
stack<double> mixed;
|
||
|
||
deck() {
|
||
// setup the mixed deck
|
||
for (map<string, double>::iterator i = this->deck_specifics_a.begin(); i != this->deck_specifics_a.end(); ++i) {
|
||
// random sort the cards
|
||
int deck_n = this->getRandom(1, 5, 0);
|
||
switch (deck_n) {
|
||
case 1:
|
||
this->deck_1.push(i->second);
|
||
break;
|
||
case 2:
|
||
this->deck_2.push(i->second);
|
||
break;
|
||
case 3:
|
||
this->deck_3.push(i->second);
|
||
break;
|
||
case 4:
|
||
this->deck_4.push(i->second);
|
||
break;
|
||
case 5:
|
||
this->deck_5.push(i->second);
|
||
break;
|
||
}
|
||
}
|
||
// if debug mode we check the shuffle
|
||
vector<double> debug_deck;
|
||
// complete the shuffle
|
||
int not_again[] = {0, 0, 0, 0, 0};
|
||
int deck_n = 0;
|
||
while (true) {
|
||
// random sort the cards
|
||
deck_n = this->getRandom(1, 5, deck_n);
|
||
if (not_again[deck_n - 1] == 0) {
|
||
if (1 == deck_n && !this->deck_1.empty()) {
|
||
// add to real deck
|
||
this->mixed.push(this->deck_1.top());
|
||
if (this->debug) {
|
||
debug_deck.push_back(this->deck_1.top());
|
||
}
|
||
// remove from tem deck
|
||
this->deck_1.pop();
|
||
} else if (2 == deck_n && !this->deck_2.empty()) {
|
||
// add to real deck
|
||
this->mixed.push(this->deck_2.top());
|
||
if (this->debug) {
|
||
debug_deck.push_back(this->deck_2.top());
|
||
}
|
||
// remove from tem deck
|
||
this->deck_2.pop();
|
||
} else if (3 == deck_n && !this->deck_3.empty()) {
|
||
// add to real deck
|
||
this->mixed.push(this->deck_3.top());
|
||
if (this->debug) {
|
||
debug_deck.push_back(this->deck_3.top());
|
||
}
|
||
// remove from tem deck
|
||
this->deck_3.pop();
|
||
} else if (4 == deck_n && !this->deck_4.empty()) {
|
||
// add to real deck
|
||
this->mixed.push(this->deck_4.top());
|
||
if (this->debug) {
|
||
debug_deck.push_back(this->deck_4.top());
|
||
}
|
||
// remove from tem deck
|
||
this->deck_4.pop();
|
||
} else if (5 == deck_n && !this->deck_5.empty()) {
|
||
// add to real deck
|
||
this->mixed.push(this->deck_5.top());
|
||
if (this->debug) {
|
||
debug_deck.push_back(this->deck_5.top());
|
||
}
|
||
// remove from tem deck
|
||
this->deck_5.pop();
|
||
} else {
|
||
not_again[deck_n - 1] = 1;
|
||
}
|
||
} else {
|
||
// check we still have a zero
|
||
bool exists = std::find(begin(not_again), end(not_again), 0) != end(not_again);
|
||
// if no 0 exists then we are done
|
||
if (!exists) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
// if debug mode we check the shuffle
|
||
if (this->debug) {
|
||
// this is the current deck
|
||
cout << __LINE__ << " This is the current deck" << endl;
|
||
// setup the reverse map
|
||
for(double i : debug_deck)
|
||
cout << i << " = " << this->deck_specifics_b[i] << endl;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* A Basic Random
|
||
*/
|
||
int getRandom(int min, int max, int n) {
|
||
random_device rd;
|
||
mt19937 g(rd());
|
||
uniform_int_distribution<int> my_random(min, max);
|
||
// get random but make sure
|
||
// it is not the same as n
|
||
int r = my_random(g);
|
||
while (r == n) {
|
||
r = my_random(g);
|
||
}
|
||
return r;
|
||
}
|
||
|
||
/**
|
||
* get the card rank key
|
||
*/
|
||
int getRankKey(string key) {
|
||
// the iterator search
|
||
map<string, int>::iterator found = this->deck_ranks_a.find(key);
|
||
// check if it is found
|
||
if (found != this->deck_ranks_a.end()) {
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " getRankKey [" << key << "] => " << found->second << endl;
|
||
}
|
||
// element found;
|
||
return found->second;
|
||
}
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " getRankKey [" << key << "] => not found" << endl;
|
||
}
|
||
// element not found
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K KEYS
|
||
* H1, H2, H3 ,H4, H5, H6, H7, H8, H9, H10, HJ, HQ, HK 1 = Hearts
|
||
* D1, D2, D3 ,D4, D5, D6, D7, D8, D9, D10, DJ, DQ, DK 2 = Diamonds
|
||
* S1, S2, S3 ,S4, S5, S6, S7, S8, S9, S10, SJ, SQ, SK 3 = Spades
|
||
* C1, C2, C3 ,C4, C5, C6, C7, C8, C9, C10, CJ, CQ, CK 4 = Clubs
|
||
**/
|
||
void showSelection() {
|
||
// show all SPECIFIC options
|
||
if (this->mode == 2) {
|
||
cout << "H1 = Ace of Hearts" << endl;
|
||
cout << "H2 = Two of Hearts" << endl;
|
||
cout << "H3 = Three of Hearts" << endl;
|
||
cout << "H4 = Four of Hearts" << endl;
|
||
cout << "H5 = Five of Hearts" << endl;
|
||
cout << "H6 = Six of Hearts" << endl;
|
||
cout << "H7 = Seven of Hearts" << endl;
|
||
cout << "H8 = Eight of Hearts" << endl;
|
||
cout << "H9 = Nine of Hearts" << endl;
|
||
cout << "H10 = Ten of Hearts" << endl;
|
||
cout << "HJ = Jack of Hearts" << endl;
|
||
cout << "HQ = Queen of Hearts" << endl;
|
||
cout << "HK = King of Hearts" << endl;
|
||
|
||
cout << "D1 = Ace of Diamonds" << endl;
|
||
cout << "D2 = Two of Diamonds" << endl;
|
||
cout << "D3 = Tree of Diamonds" << endl;
|
||
cout << "D4 = Four of Diamonds" << endl;
|
||
cout << "D5 = Five of Diamonds" << endl;
|
||
cout << "D6 = Six of Diamonds" << endl;
|
||
cout << "D7 = Seven of Diamonds" << endl;
|
||
cout << "D8 = Eight of Diamonds" << endl;
|
||
cout << "D9 = Nine of Diamonds" << endl;
|
||
cout << "D10 = Ten of Diamonds" << endl;
|
||
cout << "DJ = Jack of Diamonds" << endl;
|
||
cout << "DQ = Queen of Diamonds" << endl;
|
||
cout << "DK = King of Diamonds" << endl;
|
||
|
||
cout << "S1 = Ace of Spades" << endl;
|
||
cout << "S2 = Two of Spades" << endl;
|
||
cout << "S3 = Tree of Spades" << endl;
|
||
cout << "S4 = Four of Spades" << endl;
|
||
cout << "S5 = Five of Spades" << endl;
|
||
cout << "S6 = Six of Spades" << endl;
|
||
cout << "S7 = Seven of Spades" << endl;
|
||
cout << "S8 = Eight of Spades" << endl;
|
||
cout << "S9 = Nine of Spades" << endl;
|
||
cout << "S10 = Ten of Spades" << endl;
|
||
cout << "SJ = Jack of Spades" << endl;
|
||
cout << "SQ = Queen of Spades" << endl;
|
||
cout << "SK = King of Spades" << endl;
|
||
|
||
cout << "C1 = Ace of Clubs" << endl;
|
||
cout << "C2 = Two of Clubs" << endl;
|
||
cout << "C3 = Tree of Clubs" << endl;
|
||
cout << "C4 = Four of Clubs" << endl;
|
||
cout << "C5 = Five of Clubs" << endl;
|
||
cout << "C6 = Six of Clubs" << endl;
|
||
cout << "C7 = Seven of Clubs" << endl;
|
||
cout << "C8 = Eight of Clubs" << endl;
|
||
cout << "C9 = Nine of Clubs" << endl;
|
||
cout << "C10 = Ten of Clubs" << endl;
|
||
cout << "CJ = Jack of Clubs" << endl;
|
||
cout << "CQ = Queen of Clubs" << endl;
|
||
cout << "CK = King of Clubs" << endl;
|
||
} else {
|
||
// show all RANK options
|
||
cout << "1 = Ace" << endl;
|
||
cout << "2 = Two" << endl;
|
||
cout << "3 = Three" << endl;
|
||
cout << "4 = Four" << endl;
|
||
cout << "5 = Five" << endl;
|
||
cout << "6 = Six" << endl;
|
||
cout << "7 = Seven" << endl;
|
||
cout << "8 = Eight" << endl;
|
||
cout << "9 = Nine" << endl;
|
||
cout << "10 = Ten" << endl;
|
||
cout << "J = Jack" << endl;
|
||
cout << "Q = Queen" << endl;
|
||
cout << "K = King " << endl;
|
||
}
|
||
}
|
||
};
|
||
|
||
class hand : public cardDB {
|
||
protected:
|
||
// the deck in each and
|
||
bool cards[13][4] = {};
|
||
// when cards are lose
|
||
vector<double> lose;
|
||
|
||
// the setter
|
||
bool set(double card, bool state) {
|
||
int rank, shape;
|
||
rank = (int) card;
|
||
shape = (int) (card * 10000);
|
||
shape = (shape - (rank * 10000)) / 1000;
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " set [" << card << "] R=" << rank << " S=" << shape << " state=" << state << endl;
|
||
}
|
||
// set the state
|
||
return this->set(rank, shape, state);
|
||
}
|
||
|
||
bool set(int rank, int shape, bool state) {
|
||
// now set the card state
|
||
this->cards[rank][shape] = state;
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " set R=" << rank << " S=" << shape << " state=" << state << endl;
|
||
}
|
||
// always true :)
|
||
return true;
|
||
}
|
||
|
||
// remove the cards locally
|
||
bool remove(double card, bool found = false) {
|
||
// check if this card is in the deck
|
||
if (found || this->searchDeck(card)) {
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " removed=" << card << endl;
|
||
}
|
||
// was removed so true
|
||
return this->set(card, false);
|
||
}
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " not removed=" << card << endl;
|
||
}
|
||
// was not removed
|
||
return false;
|
||
}
|
||
|
||
// remove the card locally (may not be needed)
|
||
bool remove(string card, bool found = false) {
|
||
// check if this card is in the deck
|
||
if (found || this->searchDeck(card)) {
|
||
// get the double
|
||
double d_card = this->get(card);
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " removed=[" << d_card << "]=" << card << endl;
|
||
}
|
||
// was removed so true
|
||
return this->set(d_card, false);
|
||
}
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " not removed=" << card << endl;
|
||
}
|
||
// was not removed
|
||
return false;
|
||
}
|
||
|
||
// remove the cards locally (may not be needed)
|
||
bool remove(int rank) {
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " removed=" << rank << endl;
|
||
}
|
||
// there can only be four ranks
|
||
for (int shape = 1; shape < 5; shape++) {
|
||
this->set(rank, shape, false);
|
||
}
|
||
// aways true
|
||
return true;
|
||
}
|
||
|
||
// the getter
|
||
bool has(int rank, int shape) {
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " has R=" << rank << " S=" << shape << " answer=" << this->cards[rank][shape] << endl;
|
||
}
|
||
// now add the card
|
||
return this->cards[rank][shape];
|
||
}
|
||
|
||
// the getter RANK
|
||
bool has(int rank, bool give) {
|
||
bool found = false;
|
||
for (int s = 1; s < 5; s++) {
|
||
if (this->cards[rank][s]) {
|
||
double r = this->getDoubleKey(rank, s);
|
||
// show values in debugging
|
||
if (this->debug && give){
|
||
cout << __LINE__ << " has & give R=" << rank << " S=" << s << " answer=1" << " [" << r << "]" << endl;
|
||
} else if (this->debug){
|
||
cout << __LINE__ << " has R=" << rank << " S=" << s << " answer=1" << " [" << r << "]" << endl;
|
||
}
|
||
// give value to another player
|
||
if (give) {
|
||
this->lose.push_back(r);
|
||
}
|
||
found = true;
|
||
}
|
||
}
|
||
// now add the card
|
||
return found;
|
||
}
|
||
|
||
public:
|
||
// show players hand
|
||
void showHand() {
|
||
bool none = true;
|
||
for (int r = 1; r < 14; r++) {
|
||
for (int s = 1; s < 5; s++) {
|
||
if (this->cards[r][s]) {
|
||
// get the key
|
||
double card = this->getDoubleKey(r, s);
|
||
// show this card
|
||
cout << this->deck_specifics_b[card] << ") " << this->deck_display[this->deck_specifics_b[card]]
|
||
<< endl;
|
||
none = false;
|
||
}
|
||
}
|
||
}
|
||
// give empty hand message if no cards found
|
||
if (none) {
|
||
cout << "Your hand is empty :)" << endl;
|
||
}
|
||
}
|
||
|
||
// set the cards locally
|
||
bool add(int card) {
|
||
// check if this card is in the deck
|
||
if (this->searchDeck(card)) {
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " add " << card << endl;
|
||
}
|
||
// was set so true
|
||
return this->set(card, true);
|
||
}
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " did not add " << card << endl;
|
||
}
|
||
// was not set
|
||
return false;
|
||
}
|
||
|
||
// set the cards locally
|
||
bool add(double card) {
|
||
// check if this card is in the deck
|
||
if (this->searchDeck(card)) {
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " add " << card << endl;
|
||
}
|
||
// was set so true
|
||
return this->set(card, true);
|
||
}
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " did not add " << card << endl;
|
||
}
|
||
// was not set
|
||
return false;
|
||
}
|
||
|
||
// set the cards locally (may not be needed)
|
||
bool add(string card) {
|
||
// check if this card is in the deck
|
||
if (this->searchDeck(card)) {
|
||
// get the double
|
||
double d_card = this->get(card);
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " add [" << d_card << "] " << card << endl;
|
||
}
|
||
// was set so true
|
||
return this->set(d_card, true);
|
||
}
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " did not add " << card << endl;
|
||
}
|
||
// was not set
|
||
return false;
|
||
}
|
||
|
||
// set the cards locally
|
||
bool hasCard(double card, bool give) {
|
||
// always rest the lose
|
||
this->lose.clear();
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " we clear the lose vector" << endl;
|
||
}
|
||
// check if this card is in the deck
|
||
if (this->searchDeck(card)) {
|
||
int rank, shape;
|
||
rank = (int) card;
|
||
shape = (int) (card * 10000);
|
||
shape = (shape - (rank * 10000)) / 1000;
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " has card [" << card << "]" << " R=" << rank << " S=" << shape << endl;
|
||
}
|
||
// check if we must remove it at the same time
|
||
if (give) {
|
||
// get the card
|
||
if (this->has(rank, shape)) {
|
||
// remove since it is found
|
||
return this->remove(card, true);
|
||
}
|
||
// not found
|
||
return false;
|
||
}
|
||
// return if the card is found
|
||
return this->has(rank, shape);
|
||
}
|
||
// not a card
|
||
return false;
|
||
}
|
||
|
||
// set the card RANK locally
|
||
bool hasCard(int card, bool give) {
|
||
// always rest the lose
|
||
this->lose.clear();
|
||
// check if this card is in the deck
|
||
if (card > 0 && card < 14) {
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " has card [" << card << "]" << endl;
|
||
}
|
||
// check if we must remove it at the same time
|
||
if (give) {
|
||
// get the card
|
||
if (this->has(card, give)) {
|
||
// remove since it is found
|
||
for (double c : this->lose) {
|
||
// show values in debugging
|
||
if (this->debug) {
|
||
cout << __LINE__ << " lose [" << c << "]" << endl;
|
||
}
|
||
this->remove(c, true);
|
||
}
|
||
return true;
|
||
}
|
||
// not found
|
||
return false;
|
||
}
|
||
// return if the card is found
|
||
return this->has(card, give);
|
||
}
|
||
// not a card
|
||
return false;
|
||
}
|
||
|
||
// set the cards locally (may not be needed)
|
||
bool hasCard(string card, bool give) {
|
||
// always rest the lose
|
||
this->lose.clear();
|
||
// check if this card is in the deck
|
||
if (this->searchDeck(card)) {
|
||
// get the double
|
||
double d_card = this->get(card);
|
||
int rank, shape;
|
||
rank = (int) d_card;
|
||
shape = (int) (d_card * 10000);
|
||
shape = (shape - (rank * 10000)) / 1000;
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " has card [" << card << "=" << d_card << "]" << " R=" << rank << " S=" << shape << endl;
|
||
}
|
||
// check if we must remove it at the same time
|
||
if (give) {
|
||
// get the card
|
||
if (this->has(rank, shape)) {
|
||
// remove since it is found
|
||
return this->remove(d_card);
|
||
}
|
||
// not found
|
||
return false;
|
||
}
|
||
// return if the card is found
|
||
return this->has(rank, shape);
|
||
}
|
||
// not a card
|
||
return false;
|
||
}
|
||
|
||
// get your loses to those asking RANK
|
||
vector<double> getWinnings() {
|
||
return this->lose;
|
||
}
|
||
|
||
// ask for a card
|
||
bool askCard(int card, hand &AHand) {
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " ask [" << card << "]" << endl;
|
||
}
|
||
if (card > 0 && AHand.hasCard(card, true)) {
|
||
vector<double> winnings = AHand.getWinnings();
|
||
for (double c : winnings) {
|
||
// show values in debugging
|
||
if (this->debug) {
|
||
cout << __LINE__ << " winning [" << c << "]" << endl;
|
||
}
|
||
if (!this->add(c)){
|
||
if (this->debug){
|
||
cout << __LINE__ << " winning ERROR->[" << c << "]" << endl;
|
||
}
|
||
// break on error
|
||
return false;
|
||
}
|
||
}
|
||
// cards were found
|
||
return true;
|
||
}
|
||
// cards were not found
|
||
return false;
|
||
}
|
||
|
||
// ask for a card
|
||
bool askCard(double card, hand &AHand) {
|
||
// show values in debugging
|
||
if (this->debug){
|
||
cout << __LINE__ << " ask [" << card << "]" << endl;
|
||
}
|
||
if (AHand.hasCard(card, true)) {
|
||
// show values in debugging
|
||
if (this->debug) {
|
||
cout << __LINE__ << " before add [" << card << "]" << endl;
|
||
}
|
||
// cards were found
|
||
return this->add(card);
|
||
}
|
||
// cards were not found
|
||
return false;
|
||
}
|
||
|
||
// ask for a card
|
||
bool askCard(string card, hand &AHand) {
|
||
return this->askCard(this->get(card), AHand);
|
||
}
|
||
};
|
||
|
||
class game : public deck {
|
||
protected:
|
||
// game status
|
||
bool status;
|
||
// number of payers
|
||
int players;
|
||
// deceit in mode = 2 (can ask for a card you already have in your hand, or not)
|
||
bool deceit;
|
||
// allow empty deck
|
||
bool empty_deck;
|
||
// player hands
|
||
map<int, hand> hands;
|
||
|
||
// opening setup
|
||
void setupBoard() {
|
||
// for quick testing
|
||
this->players = 2;
|
||
this->mode = 1;
|
||
this->empty_deck = false;
|
||
return;
|
||
// string to get answers
|
||
string tmp;
|
||
// ask the opening questions
|
||
while (true) {
|
||
cout << "How many players will play?" << endl;
|
||
cout << "[2-6]: ";
|
||
cin >> this->players;
|
||
if (this->players > 1 && this->players < 7) {
|
||
break;
|
||
}
|
||
cin.clear();
|
||
cin.ignore();
|
||
cout << "Must be between 2 and 6 players." << endl;
|
||
}
|
||
// get the game mode
|
||
while (true) {
|
||
cout << "Will players be asking per [R]ank or for [S]pecific cards?" << endl;
|
||
cout << "(r/s): ";
|
||
cin >> tmp;
|
||
if (tmp == "r" || tmp == "R" || tmp == "Rank" || tmp == "rank") {
|
||
this->mode = 1;
|
||
break;
|
||
} else if (tmp == "s" || tmp == "S" || tmp == "Specific" || tmp == "specific") {
|
||
this->mode = 2;
|
||
break;
|
||
}
|
||
cin.clear();
|
||
cin.ignore();
|
||
cout << "Lets try again, please answer only r or s" << endl;
|
||
}
|
||
// only allow deceit when in specific this->mode
|
||
if (this->mode == 2) {
|
||
while (true) {
|
||
cout << "Will players be allowed to ask for cards they have?" << endl;
|
||
cout << "(y/n): ";
|
||
cin >> tmp;
|
||
if (tmp == "y" || tmp == "Y" || tmp == "yes" || tmp == "Yes") {
|
||
this->deceit = true;
|
||
break;
|
||
} else if (tmp == "n" || tmp == "N" || tmp == "no" || tmp == "No") {
|
||
this->deceit = false;
|
||
break;
|
||
}
|
||
cin.clear();
|
||
cin.ignore();
|
||
cout << "Lets try again, please answer only y or n" << endl;
|
||
}
|
||
}
|
||
// check if empty deck is allowed
|
||
while (true) {
|
||
cout << "Will the game continue if the deck is empty?" << endl;
|
||
cout << "(y/n): ";
|
||
cin >> tmp;
|
||
if (tmp == "y" || tmp == "Y" || tmp == "yes" || tmp == "Yes") {
|
||
this->empty_deck = true;
|
||
break;
|
||
} else if (tmp == "n" || tmp == "N" || tmp == "no" || tmp == "No") {
|
||
this->empty_deck = false;
|
||
break;
|
||
}
|
||
cin.clear();
|
||
cin.ignore();
|
||
cout << "Lets try again, please answer only y or n" << endl;
|
||
}
|
||
}
|
||
|
||
// deal the cards
|
||
void dealCards() {
|
||
// deal cards
|
||
int number = 6;
|
||
if (this->players == 2) {
|
||
number = 7;
|
||
}
|
||
int p = 1;
|
||
while (p <= this->players) {
|
||
// load only the number of cards allowed
|
||
for (int card = 1; card <= number; ++card) {
|
||
this->hands[p].add(this->mixed.top());
|
||
this->mixed.pop();
|
||
}
|
||
// set player
|
||
p++;
|
||
}
|
||
}
|
||
|
||
// get a card (go fish)
|
||
double getCard(int player) {
|
||
// check if we still have cards
|
||
if (!this->mixed.empty()) {
|
||
// get the next card from the stack
|
||
double card = this->mixed.top();
|
||
this->mixed.pop();
|
||
// add to player
|
||
this->hands[player].add(card);
|
||
// return the card
|
||
return card;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
public:
|
||
game() {
|
||
// game has started
|
||
status = true;
|
||
// do opening setup
|
||
this->setupBoard();
|
||
// deal the cards
|
||
this->dealCards();
|
||
}
|
||
|
||
// play the game
|
||
void startGame() {
|
||
// we start with a random player
|
||
int p = this->getRandom(1, this->players, 0);
|
||
// get new player
|
||
bool get_new_player = false;
|
||
// show whole key set
|
||
string yes;
|
||
cout << "Before we start, here is the list of all the keys of each card." << endl;
|
||
this->showSelection();
|
||
while (true) {
|
||
if (this->mode == 1) {
|
||
cout << "So J is the key for all Jacks" << endl;
|
||
} else {
|
||
cout << "So H1 is the key for Ace of Hearts" << endl;
|
||
}
|
||
cout << "Player [" << p << "] are you ready to continue?" << endl;
|
||
cout << "(y/n): ";
|
||
cin >> yes;
|
||
if (yes == "y" || yes == "Y" || yes == "yes" || yes == "Yes") {
|
||
break;
|
||
}
|
||
cin.clear();
|
||
cin.ignore();
|
||
}
|
||
// check if we still have cards
|
||
while (status) {
|
||
// check if we must get the next player
|
||
if (get_new_player) {
|
||
// get the next player
|
||
p = p + 1;
|
||
// if the player is beyond the list (start at player one)
|
||
if (p > this->players) {
|
||
p = 1;
|
||
}
|
||
// little pause to setup the new player
|
||
while (true) {
|
||
cout << "Player [" << p << "] are you ready to continue?" << endl;
|
||
cout << "(y/n): ";
|
||
cin >> yes;
|
||
if (yes == "y" || yes == "Y" || yes == "yes" || yes == "Yes") {
|
||
break;
|
||
}
|
||
cin.clear();
|
||
cin.ignore();
|
||
}
|
||
// reset getting new player
|
||
get_new_player = false;
|
||
}
|
||
// asking temp INT/string
|
||
int tmp;
|
||
// asking who is the next player
|
||
int ask;
|
||
// last player
|
||
int l = this->players;
|
||
// first player
|
||
int f = 1;
|
||
// ask for the next player
|
||
bool ask_next = true;
|
||
if (this->players > 2) {
|
||
// if the player is the first, then move to 2
|
||
if (p == 1) {
|
||
f = 2;
|
||
}
|
||
// if the last is the player, that a step back
|
||
if (l == p) {
|
||
l = this->players - 1;
|
||
}
|
||
} else {
|
||
// do not ask for the next player
|
||
ask_next = false;
|
||
// just ask the next player
|
||
ask = 1;
|
||
if (p == 1) {
|
||
ask = 2;
|
||
}
|
||
}
|
||
// check if we should ask for next player
|
||
if (ask_next) {
|
||
cout << "We will show your hand in a moment." << endl;
|
||
while (true) {
|
||
cout << "Please select a player you would like to ask between:" << endl;
|
||
cout << "[" << f << " - " << l << "] ";
|
||
cin >> tmp;
|
||
if (tmp >= f && tmp <= l && tmp != p) {
|
||
ask = tmp;
|
||
break;
|
||
}
|
||
cin.clear();
|
||
cin.ignore();
|
||
cout << "Lets try again, you are player [" << p << "]" << endl;
|
||
}
|
||
}
|
||
// get the card to ask for
|
||
string card;
|
||
while (true) {
|
||
cout << "This is your current hand:" << endl;
|
||
this->hands[p].showHand();
|
||
cout << "What card do you want to ask for?" << endl;
|
||
cin >> card;
|
||
// make string uppercase
|
||
transform(card.begin(), card.end(), card.begin(), ::toupper);
|
||
if (this->searchDeck(card)) {
|
||
break;
|
||
}
|
||
cin.clear();
|
||
cin.ignore();
|
||
cout << "Lets try again" << endl;
|
||
}
|
||
// make sure to get INT if RANK mode
|
||
bool found_card = false;
|
||
if (this->mode == 1) {
|
||
found_card = this->hands[p].askCard(this->getRankKey(card), this->hands[ask]);
|
||
} else {
|
||
found_card = this->hands[p].askCard(card, this->hands[ask]);
|
||
}
|
||
// now lets ask
|
||
if (found_card) {
|
||
cout << endl;
|
||
// load cards of RANK
|
||
if (this->mode == 2) {
|
||
cout << " Yes! Player [" << ask << "] had the card!" << endl;
|
||
} else {
|
||
cout << " Yes! Player [" << ask << "] had the card/s!" << endl;
|
||
}
|
||
cout << " YOU GET TO GO AGAIN :)" << endl;
|
||
cout << endl;
|
||
cout << endl;
|
||
} else {
|
||
cout << "Go fish................................" << endl;
|
||
// load the card from the deck and add to player
|
||
double c = this->getCard(p);
|
||
// we must check if we found what we where looking for
|
||
if (c > 0) {
|
||
if (this->mode == 2 && c == this->get(card)) {
|
||
cout << endl;
|
||
cout << " Wow you got the card you were looking for!" << endl;
|
||
cout << " OU GET TO GO AGAIN :)" << endl;
|
||
cout << endl;
|
||
cout << endl;
|
||
} else {
|
||
cout << "The new card was added to your hand...." << endl;
|
||
// player questions
|
||
cout << "Player [" << p << "] your turn is over." << endl;
|
||
cout << endl << endl << endl << endl << endl << endl;
|
||
cout << endl << endl << endl << endl << endl << endl;
|
||
cout << endl << endl << endl << endl << endl << endl;
|
||
get_new_player = true;
|
||
}
|
||
} else {
|
||
// check if we allow empty decks
|
||
if (!this->empty_deck) {
|
||
// deck is empty so stop the game
|
||
status = false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
int main() {
|
||
|
||
// get the game
|
||
game *Game = new game();
|
||
// start game
|
||
Game->startGame();
|
||
|
||
// clear memory
|
||
delete(Game);
|
||
|
||
return 0;
|
||
}
|