-
-
Save rysu94/f1cb887d5dbedbe72f9a81710a901f3e to your computer and use it in GitHub Desktop.
C++ code for a Euchre card game simulator including rudimentary AI
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// File Name: Card.cpp | |
// By: Ryan Su | |
//uniqname: rysu | |
#include "Card.h" | |
#include <iostream> | |
#include <string> | |
using namespace std; | |
//========================================================================== | |
//Helper functions prototypes | |
//========================================================================== | |
static int convertRank(const Card &card_in); | |
static int convertSuit(const Card &card_in); | |
static int convertSuit(const Card &card_in, const string &trump); | |
static int convertSuit(const Card &card_in, const string &trump, const Card &led_card); | |
//========================================================================== | |
//Card Starter file | |
//========================================================================== | |
const string Card::RANK_TWO = "Two"; | |
const string Card::RANK_THREE = "Three"; | |
const string Card::RANK_FOUR = "Four"; | |
const string Card::RANK_FIVE = "Five"; | |
const string Card::RANK_SIX = "Six"; | |
const string Card::RANK_SEVEN = "Seven"; | |
const string Card::RANK_EIGHT = "Eight"; | |
const string Card::RANK_NINE = "Nine"; | |
const string Card::RANK_TEN = "Ten"; | |
const string Card::RANK_JACK = "Jack"; | |
const string Card::RANK_QUEEN = "Queen"; | |
const string Card::RANK_KING = "King"; | |
const string Card::RANK_ACE = "Ace"; | |
const string Card::SUIT_SPADES = "Spades"; | |
const string Card::SUIT_HEARTS = "Hearts"; | |
const string Card::SUIT_CLUBS = "Clubs"; | |
const string Card::SUIT_DIAMONDS = "Diamonds"; | |
//================================================== | |
// Suits in order from lowest suit to highest suit. | |
static const string SUIT_NAMES_BY_WEIGHT[] = { | |
Card::SUIT_SPADES, | |
Card::SUIT_HEARTS, | |
Card::SUIT_CLUBS, | |
Card::SUIT_DIAMONDS | |
}; | |
static const int NUM_SUITS = 4; | |
// Ranks in order from lowest rank to highest rank. | |
static const string RANK_NAMES_BY_WEIGHT[] = { | |
Card::RANK_TWO, | |
Card::RANK_THREE, | |
Card::RANK_FOUR, | |
Card::RANK_FIVE, | |
Card::RANK_SIX, | |
Card::RANK_SEVEN, | |
Card::RANK_EIGHT, | |
Card::RANK_NINE, | |
Card::RANK_TEN, | |
Card::RANK_JACK, | |
Card::RANK_QUEEN, | |
Card::RANK_KING, | |
Card::RANK_ACE | |
}; | |
static const int NUM_RANKS = 13; | |
//========================================================================== | |
// Defining the card class functions | |
//========================================================================== | |
Card::Card(const string &rank_in, const string &suit_in) | |
: rank(rank_in), suit(suit_in) {} | |
string Card::get_rank() const {return rank;} | |
string Card::get_suit() const {return suit;} | |
string Card::get_suit(const string &trump) const | |
{ | |
//determines the cross suit | |
string oppositeSuit; | |
/*if(trump == SUIT_DIAMONDS) | |
{ | |
oppositeSuit = SUIT_HEARTS; | |
} | |
else if(trump == SUIT_HEARTS) | |
{ | |
oppositeSuit = SUIT_DIAMONDS; | |
} | |
else if(trump == SUIT_CLUBS) | |
{ | |
oppositeSuit = SUIT_SPADES; | |
} | |
else if(trump == SUIT_SPADES) | |
{ | |
oppositeSuit = SUIT_CLUBS; | |
} | |
*/ | |
oppositeSuit = Suit_next(trump); | |
//checks the conditon if the card is the left bower | |
if(rank == RANK_JACK && suit == oppositeSuit) | |
{ | |
return trump; | |
} | |
else | |
{ | |
return suit; | |
} | |
} | |
bool Card::is_face() const | |
{ | |
if(rank == RANK_JACK || rank == RANK_QUEEN || | |
rank == RANK_KING || rank == RANK_ACE) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
bool Card::is_right_bower(const string &trump) const | |
{ | |
if(suit == trump && rank == RANK_JACK) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
bool Card::is_left_bower(const string &trump) const | |
{ | |
string oppositeSuit; | |
/*if(trump == SUIT_DIAMONDS) | |
{ | |
oppositeSuit = SUIT_HEARTS; | |
} | |
else if(trump == SUIT_HEARTS) | |
{ | |
oppositeSuit = SUIT_DIAMONDS; | |
} | |
else if(trump == SUIT_CLUBS) | |
{ | |
oppositeSuit = SUIT_SPADES; | |
} | |
else if(trump == SUIT_SPADES) | |
{ | |
oppositeSuit = SUIT_CLUBS; | |
} | |
*/ | |
oppositeSuit = Suit_next(trump); | |
//check if it is left bower | |
if(get_suit() == oppositeSuit && rank == RANK_JACK) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
bool Card::is_trump(const string &trump) const | |
{ | |
if(suit == trump) | |
{ | |
return true; | |
} | |
else if(get_suit(suit) == trump && rank == RANK_JACK) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
//========================================================================== | |
//Helper Functions | |
//========================================================================== | |
//Requires: Card has to have varaiable rank defined and follow rank naming convention | |
//Modifies: boolean operators and card_less | |
//Effect: Converts a card's rank into a int, ie RANK_TWO = 2, RANK_JACK = 11. | |
static int convertRank(const Card &card_in) | |
{ | |
//get the card rank | |
string cardVal = card_in.get_rank(); | |
//convert ranks into ints, default = 0 | |
int cardNum = 0; | |
for(int i = 0; i < NUM_RANKS; ++i) | |
{ | |
if(RANK_NAMES_BY_WEIGHT[i] == cardVal) | |
{ | |
cardNum = i + 2; | |
} | |
} | |
return cardNum; | |
} | |
//Requires: Card has to have varaiable suit defined and follow suit naming convention | |
//Modifies: boolean operators and card_less | |
//Effect: Converts a card's suit into a int, ie SUIT_HEARTS = 2. Breaks ties between rank. | |
static int convertSuit(const Card &card_in) | |
{ | |
//get card suit | |
string cardVal = card_in.get_suit(); | |
//convert ranks into ints, default = 0 | |
int cardNum = 0; | |
//weight of the suits | |
for(int i = 0; i < NUM_SUITS; ++i) | |
{ | |
if(SUIT_NAMES_BY_WEIGHT[i] == cardVal) | |
{ | |
cardNum = i + 1; | |
} | |
} | |
return cardNum; | |
} | |
//Requires: Card has to have varaiable suit defined and follow suit naming convention | |
//Modifies: boolean operators and card_less | |
//Effect: Converts a card's suit into a int, ie SUIT_HEARTS = 2 returns 1 if | |
// card::rank does not follow naming convention. Takes trump into account. | |
static int convertSuit(const Card &card_in, const string &trump) | |
{ | |
//get card suit | |
string cardVal = card_in.get_suit(trump); | |
//convert suit into a number, default 1 | |
int cardNum = 1; | |
//weight of the trump | |
if(cardVal == trump) | |
{ | |
cardNum = cardNum * 1000; | |
} | |
//weight of left bower | |
if (card_in.is_left_bower(trump)) | |
{ | |
cardNum = cardNum * 100; | |
} | |
//weight of right bower | |
if(card_in.is_right_bower(trump)) | |
{ | |
cardNum = cardNum * 1000; | |
} | |
return cardNum; | |
} | |
//Requires: Card has to have varaiable suit defined and follow suit naming convention | |
//Modifies: Nothing | |
//Effect: Converts a card's suit into a int, ie SUIT_HEARTS = 2 returns 1 if | |
// card::rank does not follow naming convention. Takes trump and led card into account | |
static int convertSuit(const Card &card_in, const string &trump, const Card &led_card) | |
{ | |
//get card suit | |
string cardVal = card_in.get_suit(trump); | |
string ledCardVal = led_card.get_suit(trump); | |
//convert suit into a number, default 1 | |
int cardNum = 1; | |
//weight of the led card suit | |
if(cardVal == ledCardVal) | |
{ | |
cardNum = cardNum * 100; | |
} | |
//weight of the trump suit | |
if(cardVal == trump) | |
{ | |
cardNum = cardNum * 1000; | |
} | |
//weight of left bower | |
if (card_in.is_left_bower(trump)) | |
{ | |
cardNum = cardNum * 100; | |
} | |
//weight of right bower | |
if(card_in.is_right_bower(trump)) | |
{ | |
cardNum = cardNum * 1000; | |
} | |
return cardNum; | |
} | |
//========================================================================== | |
// Defining the boolean operators | |
//========================================================================== | |
bool operator<(const Card &lhs, const Card &rhs) | |
{ | |
if(convertRank(lhs) < convertRank(rhs)) | |
{ | |
return true; | |
} | |
//if they are equal value factor in suit | |
else if(convertRank(lhs) == convertRank(rhs)) | |
{ | |
if(convertSuit(lhs) < convertSuit(rhs)) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
bool operator>(const Card &lhs, const Card &rhs) | |
{ | |
if(convertRank(lhs) > convertRank(rhs)) | |
{ | |
return true; | |
} | |
//if they are equal value facto rin suit | |
else if(convertRank(lhs) == convertRank(rhs)) | |
{ | |
if(convertSuit(lhs) > convertSuit(rhs)) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
bool operator==(const Card &lhs, const Card &rhs) | |
{ | |
//check their value | |
if(convertRank(lhs) == convertRank(rhs)) | |
{ | |
//check their suit | |
if(convertSuit(lhs) == convertSuit(rhs)) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
bool operator!=(const Card &lhs, const Card &rhs) | |
{ | |
if(convertRank(lhs) != convertRank(rhs)) | |
{ | |
return true; | |
} | |
//if they are same value check suit | |
else if(convertRank(lhs) != convertRank(rhs)) | |
{ | |
if(convertSuit(lhs) != convertSuit(rhs)) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
//========================================================================== | |
// Defining the other functions | |
//========================================================================== | |
string Suit_next(const string &suit) | |
{ | |
if(suit == Card::SUIT_DIAMONDS) | |
{ | |
return Card::SUIT_HEARTS; | |
} | |
else if(suit == Card::SUIT_HEARTS) | |
{ | |
return Card::SUIT_DIAMONDS; | |
} | |
else if(suit == Card::SUIT_CLUBS) | |
{ | |
return Card::SUIT_SPADES; | |
} | |
return Card::SUIT_CLUBS; | |
} | |
ostream& operator<<(ostream &os, const Card &card) | |
{ | |
os << (card.get_rank()) << " of " << (card.get_suit()); | |
return os; | |
} | |
bool Card_less(const Card &a, const Card &b, const string &trump) | |
{ | |
int aConvertedVal = 1; | |
int bConvertedVal = 1; | |
aConvertedVal = convertRank(a) * convertSuit(a, trump); | |
bConvertedVal = convertRank(b) * convertSuit(b, trump); | |
if(aConvertedVal < bConvertedVal) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
bool Card_less(const Card &a, const Card &b, const Card &led_card, const std::string &trump) | |
{ | |
int aConvertedVal = 1; | |
int bConvertedVal = 1; | |
aConvertedVal = convertRank(a) * convertSuit(a, trump, led_card); | |
bConvertedVal = convertRank(b) * convertSuit(b, trump, led_card); | |
if(aConvertedVal < bConvertedVal) | |
{ | |
//cout << aConvertedVal << " " << bConvertedVal << endl; | |
return true; | |
} | |
else | |
{ | |
//cout << aConvertedVal << " " << bConvertedVal << endl; | |
return false; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef CARD_H | |
#define CARD_H | |
/* Card.h | |
* | |
* Represents a single playing card | |
* | |
* by Andrew DeOrio | |
* awdeorio@umich.edu | |
* 2014-12-21 | |
*/ | |
#include <iostream> | |
#include <string> | |
class Card { | |
public: | |
// rank and suit names | |
static const std::string RANK_TWO; | |
static const std::string RANK_THREE; | |
static const std::string RANK_FOUR; | |
static const std::string RANK_FIVE; | |
static const std::string RANK_SIX; | |
static const std::string RANK_SEVEN; | |
static const std::string RANK_EIGHT; | |
static const std::string RANK_NINE; | |
static const std::string RANK_TEN; | |
static const std::string RANK_JACK; | |
static const std::string RANK_QUEEN; | |
static const std::string RANK_KING; | |
static const std::string RANK_ACE; | |
static const std::string SUIT_SPADES; | |
static const std::string SUIT_HEARTS; | |
static const std::string SUIT_CLUBS; | |
static const std::string SUIT_DIAMONDS; | |
//REQUIRES rank is one of "Two", "Three", "Four", "Five", "Six", "Seven", | |
// "Eight", "Nine", "Ten", "Jack", "Queen", "King", "Ace" | |
// suit is one of "Spades", "Hearts", "Clubs", "Diamonds" | |
//EFFECTS Initializes Card to specified rank and suit | |
Card(const std::string &rank_in, const std::string &suit_in); | |
//EFFECTS Returns the rank | |
std::string get_rank() const; | |
//EFFECTS Returns the suit. Does not consider trump. | |
std::string get_suit() const; | |
//EFFECTS Returns the suit | |
//HINT: the left bower is the trump suit! | |
std::string get_suit(const std::string &trump) const; | |
//EFFECTS Returns true if card is a face card (Jack, Queen, King or Ace) | |
bool is_face() const; | |
//EFFECTS Returns true if card is the Jack of the trump suit | |
bool is_right_bower(const std::string &trump) const; | |
//EFFECTS Returns true if card is the Jack of the next suit | |
bool is_left_bower(const std::string &trump) const; | |
//EFFECTS Returns true if the card is a trump card. All cards of the trump | |
// suit are trump cards. The left bower is also a trump card. | |
bool is_trump(const std::string &trump) const; | |
private: | |
std::string rank; | |
std::string suit; | |
}; | |
//EFFECTS Returns true if lhs is lower value than rhs. | |
// Does not consider trump. | |
bool operator<(const Card &lhs, const Card &rhs); | |
//EFFECTS Returns true if lhs is higher value than rhs. | |
// Does not consider trump. | |
bool operator>(const Card &lhs, const Card &rhs); | |
//EFFECTS Returns true if lhs is same card as rhs. | |
// Does not consider trump. | |
bool operator==(const Card &lhs, const Card &rhs); | |
//EFFECTS Returns true if lhs is not the same card as rhs. | |
// Does not consider trump. | |
bool operator!=(const Card &lhs, const Card &rhs); | |
//EFFECTS returns the next suit, which is the suit of the same color | |
std::string Suit_next(const std::string &suit); | |
//EFFECTS Prints Card to stream, for example "Two of Spades" | |
std::ostream & operator<<(std::ostream &os, const Card &card); | |
//EFFECTS Returns true if a is lower value than b. Uses trump to determine | |
// order, as described in the spec. | |
bool Card_less(const Card &a, const Card &b, const std::string &trump); | |
//EFFECTS Returns true if a is lower value than b. Uses both the trump suit | |
// and the suit led to determine order, as described in the spec. | |
bool Card_less(const Card &a, const Card &b, const Card &led_card, const std::string &trump); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// File Name: euchre.cpp | |
// By: Ryan Su | |
//uniqname: rysu | |
#include "Card.h" | |
#include "Pack.h" | |
#include "Player.h" | |
#include <vector> | |
#include <string> | |
#include <cstdlib> | |
using namespace std; | |
//========================================================================== | |
//Function prototypes | |
//========================================================================== | |
//The game struct stores data and options than will accessed during game prcessing | |
struct Game | |
{ | |
//command line arguments | |
string pack_file_name; | |
bool isShuffle; | |
int points_to_win; | |
string P0_name; | |
string P1_name; | |
string P2_name; | |
string P3_name; | |
string P0_type; | |
string P1_type; | |
string P2_type; | |
string P3_type; | |
//game data | |
int num_players; | |
int round; | |
int hand; | |
int hand_num; | |
string trump_suit; | |
string led_suit; | |
int team_1_points; | |
int team_2_points; | |
int team_1_tricks; | |
int team_2_tricks; | |
bool team_1_orderUp; | |
bool team_2_orderUp; | |
//index of dealer | |
int dealer; | |
//Player vector | |
vector<Player*> players; | |
}; | |
//========================================================================== | |
//Function prototypes | |
//========================================================================== | |
int eldestHand(int dealer); | |
void dealSequence(int dealer, Pack &deck, struct Game &Game); | |
void get_points(int &team_1_points, int &team_2_points, struct Game &Game); | |
void runHand(const string &trump, int &index_winner, struct Game &Game); | |
void makeTrump(int roundNum, const Card &upcard, int dealer, struct Game &Game); | |
//========================================================================== | |
//Function Main | |
//========================================================================== | |
int main(int argc, char *argv[]) | |
{ | |
//========================================================================== | |
//Initialization | |
//========================================================================== | |
Game Game; | |
//initialize some of the game's variables | |
Game.isShuffle = false; | |
Game.points_to_win = 0; | |
//game data | |
Game.num_players = 4; | |
Game.round = 0; | |
Game.hand = 0; | |
Game.hand_num = 0; | |
Game.team_1_points = 0; | |
Game.team_2_points = 0; | |
Game.team_1_tricks = 0; | |
Game.team_2_tricks = 0; | |
Game.team_1_orderUp = false; | |
Game.team_2_orderUp = false; | |
//index of dealer | |
Game.dealer = 0; | |
string h_string; | |
//Read command line arguments | |
h_string = argv[1]; | |
Game.pack_file_name = h_string; | |
//check error | |
h_string = argv[2]; | |
if(h_string != "shuffle" && h_string != "noshuffle") | |
{ | |
//cout << "A" << endl; | |
cout << "Usage: euchre PACK_FILENAME [shuffle|noshuffle] POINTS_TO_WIN NAME1 NAME2 NAME3 NAME4" << endl; | |
exit(EXIT_FAILURE); | |
} | |
//set shuffle mode | |
if(h_string == "shuffle") | |
{ | |
Game.isShuffle = true; | |
} | |
int h_int = atoi(argv[3]); | |
//check error | |
if(h_int < 1 || h_int > 100) | |
{ | |
//cout << "B" << endl; | |
cout << "Usage: euchre PACK_FILENAME [shuffle|noshuffle] POINTS_TO_WIN NAME1 NAME2 NAME3 NAME4" << endl; | |
exit(EXIT_FAILURE); | |
} | |
Game.points_to_win = h_int; | |
Game.P0_name = argv[4]; | |
h_string = argv[5]; | |
//check error | |
if(h_string != "Simple" && h_string != "Human") | |
{ | |
//cout << "C" << endl; | |
cout << "Usage: euchre PACK_FILENAME [shuffle|noshuffle] POINTS_TO_WIN NAME1 NAME2 NAME3 NAME4" << endl; | |
exit(EXIT_FAILURE); | |
} | |
Game.P0_type = argv[5]; | |
Game.P1_name = argv[6]; | |
h_string = argv[7]; | |
//check error | |
if(h_string != "Simple" && h_string != "Human") | |
{ | |
//cout << "D" << endl; | |
cout << "Usage: euchre PACK_FILENAME [shuffle|noshuffle] POINTS_TO_WIN NAME1 NAME2 NAME3 NAME4" << endl; | |
exit(EXIT_FAILURE); | |
} | |
Game.P1_type = argv[7]; | |
Game.P2_name = argv[8]; | |
h_string = argv[9]; | |
//check error | |
if(h_string != "Simple" && h_string != "Human") | |
{ | |
//cout << "E" << endl; | |
cout << "Usage: euchre PACK_FILENAME [shuffle|noshuffle] POINTS_TO_WIN NAME1 NAME2 NAME3 NAME4" << endl; | |
exit(EXIT_FAILURE); | |
} | |
Game.P2_type = argv[9]; | |
Game.P3_name = argv[10]; | |
h_string = argv[11]; | |
//check error | |
if(h_string != "Simple" && h_string != "Human") | |
{ | |
//cout << "F" << endl; | |
cout << "Usage: euchre PACK_FILENAME [shuffle|noshuffle] POINTS_TO_WIN NAME1 NAME2 NAME3 NAME4" << endl; | |
exit(EXIT_FAILURE); | |
} | |
Game.P3_type = argv[11]; | |
//Make Pack | |
Pack deck = Pack(Game.pack_file_name); | |
//Make Players, dynamic allocated, REMEMBER TO DELETE AT GAME END! | |
/* | |
//keep track of human players | |
vector<bool> humanPlayers; | |
h_string = Game.P0_type; | |
if(h_string == "Human") | |
{ | |
humanPlayers.push_back(true); | |
} | |
h_string = Game.P1_type; | |
else if(h_string == "Human") | |
{ | |
humanPlayers.push_back(true); | |
} | |
h_string = Game.P2_type; | |
else if(h_string == "Human") | |
{ | |
humanPlayers.push_back(true); | |
} | |
h_string = Game.P3_type; | |
else if(h_string == "Human") | |
{ | |
humanPlayers.push_back(true); | |
} | |
*/ | |
Player *P0 = Player_factory(Game.P0_name, Game.P0_type); | |
Game.players.push_back(P0); | |
Player *P1 = Player_factory(Game.P1_name, Game.P1_type); | |
Game.players.push_back(P1); | |
Player *P2 = Player_factory(Game.P2_name, Game.P2_type); | |
Game.players.push_back(P2); | |
Player *P3 = Player_factory(Game.P3_name, Game.P3_type); | |
Game.players.push_back(P3); | |
//========================================================================== | |
//Game Processing, single Round | |
//========================================================================== | |
for(int i = 0; i < 12; ++i) | |
{ | |
cout << argv[i] << " "; | |
} | |
cout << endl; | |
//keep looping hands until someone wins | |
while(Game.team_1_points < Game.points_to_win && Game.team_2_points < Game.points_to_win) | |
{ | |
//========================================================================== | |
//Shuffle pack | |
//========================================================================== | |
//check if the shuffle option is on | |
if(Game.isShuffle == true) | |
{ | |
//cout << "Shuffle" << endl; | |
deck.shuffle(); | |
} | |
//========================================================================== | |
//Deal hand 3-2-3-2 | |
//========================================================================== | |
//cout << "Dealing" << endl; | |
dealSequence(Game.dealer, deck, Game); | |
//========================================================================== | |
//Player decision to take trump | |
//========================================================================== | |
//Output processing | |
cout << "Hand " << Game.hand_num << endl; | |
cout << *(Game.players.at(Game.dealer)) << " deals" << endl; | |
Card upcard = deck.deal_one(); | |
cout << upcard << " turned up" << endl; | |
//Round 1 | |
Game.round = 1; | |
makeTrump(Game.round, upcard, Game.dealer, Game); | |
//Round 2, if there is a round 2, with screw the dealer | |
if(Game.team_1_orderUp == false && Game.team_2_orderUp == false) | |
{ | |
Game.round = 2; | |
makeTrump(Game.round, upcard, Game.dealer, Game); | |
} | |
//========================================================================== | |
//Trick Taking, 5 tricks | |
//========================================================================== | |
//determine who goes first | |
int index_first = eldestHand(Game.dealer); | |
while(Game.hand < 5) | |
{ | |
runHand(Game.trump_suit, index_first, Game); | |
++Game.hand; | |
} | |
//========================================================================== | |
//Scoring | |
//========================================================================== | |
//print which team wins the hand | |
if(Game.team_1_tricks > Game.team_2_tricks) | |
{ | |
//team 1 wins | |
cout << *Game.players.at(0) << " and " << *Game.players.at(2) << " win the hand" << endl; | |
} | |
else if(Game.team_1_tricks < Game.team_2_tricks) | |
{ | |
//team 2 wins | |
cout << *Game.players.at(1) << " and " << *Game.players.at(3) << " win the hand" << endl; | |
} | |
//pass by reference team scores. 1 for order up 3-4 tricks, 2 for march, 2 for euchre | |
get_points(Game.team_1_points, Game.team_2_points, Game); | |
//print score | |
cout << *(Game.players.at(0)) << " and " << *(Game.players.at(2)) << " have " << Game.team_1_points << " points" << endl; | |
cout << *(Game.players.at(1)) << " and " << *(Game.players.at(3)) << " have " << Game.team_2_points << " points" << endl <<endl; | |
//========================================================================== | |
//Hand end | |
//========================================================================== | |
//reset the deck pointer | |
deck.reset(); | |
//reset the hand number | |
Game.hand = 0; | |
//reset the round number | |
Game.round = 0; | |
//incremetn hand number | |
++Game.hand_num; | |
//select new dealer by index | |
Game.dealer = Game.dealer + 1; | |
if(Game.dealer > 3) | |
{ | |
Game.dealer = 0; | |
} | |
//reset the tricks | |
Game.team_1_tricks = 0; | |
Game.team_2_tricks = 0; | |
//reset order up | |
Game.team_1_orderUp = false; | |
Game.team_2_orderUp = false; | |
} | |
//annouce winners | |
if(Game.team_1_points >= Game.points_to_win) | |
{ | |
cout << *(Game.players.at(0)) << " and " << *(Game.players.at(2)) << " win!" << endl; | |
} | |
else if(Game.team_2_points >= Game.points_to_win) | |
{ | |
cout <<*(Game.players.at(1)) << " and " << *(Game.players.at(3)) << " win!" << endl; | |
} | |
//deletes the dynamically allocated players | |
delete P0; P0 = 0; | |
delete P1; P1 = 0; | |
delete P2; P2 = 0; | |
delete P3; P3 = 0; | |
} | |
//========================================================================== | |
//Helper Function implementation | |
//========================================================================== | |
//Requires: Dealer to be defined and need more than 1 player | |
//Modifies: Drawing cards and making trump | |
//Effects: Returns the index of the player with the eldest hand | |
int eldestHand(int dealer) | |
{ | |
//determine who is the dealer to determine the Eldest hand | |
int start_index = 0; | |
if(dealer == 3) | |
{ | |
start_index = 0; | |
} | |
else if(dealer >= 0 && dealer < 3) | |
{ | |
start_index = dealer + 1; | |
} | |
return start_index; | |
} | |
//Requires: Dealer to be defined and need more than 1 player | |
//Modifies: main, player hands | |
//Effects: deals 8 batches of cards to players for a total of 5 per player | |
void dealSequence(int dealer, Pack &deck, struct Game &Game) | |
{ | |
int start_index = eldestHand(dealer); | |
int batch_num = 0; | |
//determines whether 3 or 2 cards are dealt | |
bool batch_2 = false; | |
//Card dealtCard = Card(Card::RANK_TWO, Card::SUIT_SPADES); | |
//deal out 4 batches of cards alternating batches of 3-2-3-2 | |
while(batch_num < 4) | |
{ | |
//regulates the batches | |
if(batch_2 == false) | |
{ | |
//deal 3 | |
Game.players.at(start_index)->add_card(deck.deal_one()); | |
Game.players.at(start_index)->add_card(deck.deal_one()); | |
Game.players.at(start_index)->add_card(deck.deal_one()); | |
//increment player index | |
++start_index; | |
//so start_index doesn't go out of bounds | |
if(start_index > 3) | |
{ | |
start_index = 0; | |
} | |
//regulate batch size to 2 | |
batch_2 = true; | |
} | |
else if(batch_2 == true) | |
{ | |
//deal 2 | |
Game.players.at(start_index)->add_card(deck.deal_one()); | |
Game.players.at(start_index)->add_card(deck.deal_one()); | |
//increment player index | |
++start_index; | |
//so start_index doesn't go out of bounds | |
if(start_index > 3) | |
{ | |
start_index = 0; | |
} | |
//regulate batch size to 3 | |
batch_2 = false; | |
} | |
++batch_num; | |
} | |
batch_2 = false; | |
batch_num = 0; | |
//deal out 4 batches of cards alternating batches of 2-3-2-3 | |
while(batch_num < 4) | |
{ | |
//regulates the batches | |
if(batch_2 == true) | |
{ | |
//deal 3 | |
Game.players.at(start_index)->add_card(deck.deal_one()); | |
Game.players.at(start_index)->add_card(deck.deal_one()); | |
Game.players.at(start_index)->add_card(deck.deal_one()); | |
//increment player index | |
++start_index; | |
//so start_index doesn't go out of bounds | |
if(start_index > 3) | |
{ | |
start_index = 0; | |
} | |
//regulate batch size to 2 | |
batch_2 = false; | |
} | |
else if(batch_2 == false) | |
{ | |
//deal 2 | |
Game.players.at(start_index)->add_card(deck.deal_one()); | |
Game.players.at(start_index)->add_card(deck.deal_one()); | |
//increment player index | |
++start_index; | |
//so start_index doesn't go out of bounds | |
if(start_index > 3) | |
{ | |
start_index = 0; | |
} | |
//regulate batch size to 3 | |
batch_2 = true; | |
} | |
++batch_num; | |
} | |
} | |
//Requires: team_1_points and team_2_points must be below 10 and 5 tricks must be played | |
//Modifies: team_1_points or team_2_points | |
//Effects: adds score to either team 1 and team 2 based on tricks won | |
void get_points(int &team_1_points, int &team_2_points, struct Game &Game) | |
{ | |
//determine which team ordered up | |
//if team 1 ordered up | |
if(Game.team_1_orderUp == true) | |
{ | |
if(Game.team_1_tricks == 3 || Game.team_1_tricks == 4) | |
{ | |
team_1_points = team_1_points + 1; | |
} | |
else if(Game.team_1_tricks == 5) | |
{ | |
cout << "march!" << endl; | |
team_1_points = team_1_points + 2; | |
} | |
else | |
{ | |
cout << "euchred!" << endl; | |
team_2_points = team_2_points + 2; | |
} | |
} | |
//if team 2 ordered up | |
else if(Game.team_2_orderUp == true) | |
{ | |
if(Game.team_2_tricks == 3 || Game.team_2_tricks == 4) | |
{ | |
team_2_points = team_2_points + 1; | |
} | |
else if(Game.team_2_tricks == 5) | |
{ | |
cout << "march!" << endl; | |
team_2_points = team_2_points + 2; | |
} | |
else | |
{ | |
cout << "euchred!" << endl; | |
team_1_points = team_1_points + 2; | |
} | |
} | |
} | |
//Requires: player have cards in hand, trump must be chosen | |
//Modifies: stdout, scores | |
//Effects: simulates a round of trick taking | |
void runHand(const string &trump, int &index_winner, struct Game &Game) | |
{ | |
string led_suit; | |
//find who is leading the trick | |
int start_index = index_winner; | |
//index of player with highest card. | |
int index_highest = start_index; | |
if(start_index > 3) | |
{ | |
start_index = 0; | |
} | |
//1st player leading trick | |
Card highestCard = Game.players.at(start_index)->lead_card(trump); | |
Card led_card = highestCard; | |
led_suit = highestCard.get_suit(trump); | |
cout << led_card << " led by " << *(Game.players.at(start_index)) << endl; | |
//increment start_index | |
++start_index; | |
if(start_index > 3) | |
{ | |
start_index = 0; | |
} | |
//2nd player | |
Card holderCard = Game.players.at(start_index)->play_card(led_card, trump); | |
cout << holderCard << " played by " << *(Game.players.at(start_index)) << endl; | |
if(Card_less(highestCard, holderCard, led_card, trump)) | |
{ | |
highestCard = holderCard; | |
index_highest = start_index; | |
} | |
//increment start_index | |
++start_index; | |
if(start_index > 3) | |
{ | |
start_index = 0; | |
} | |
//3rd player | |
holderCard = Game.players.at(start_index)->play_card(led_card, trump); | |
cout << holderCard << " played by " << *(Game.players.at(start_index)) << endl; | |
if(Card_less(highestCard, holderCard, led_card, trump)) | |
{ | |
highestCard = holderCard; | |
index_highest = start_index; | |
} | |
//increment start_index | |
++start_index; | |
if(start_index > 3) | |
{ | |
start_index = 0; | |
} | |
//4th player | |
holderCard = Game.players.at(start_index)->play_card(led_card, trump); | |
cout << holderCard << " played by " << *(Game.players.at(start_index)) << endl; | |
if(Card_less(highestCard, holderCard, led_card, trump)) | |
{ | |
highestCard = holderCard; | |
index_highest = start_index; | |
} | |
//determine winner of trick | |
if(index_highest == 0) | |
{ | |
Game.team_1_tricks = Game.team_1_tricks + 1; | |
cout << *(Game.players.at(0)) << " takes the trick" << endl << endl; | |
} | |
else if(index_highest == 1) | |
{ | |
Game.team_2_tricks = Game.team_2_tricks + 1; | |
cout << *(Game.players.at(1)) << " takes the trick" << endl << endl; | |
} | |
else if(index_highest == 2) | |
{ | |
Game.team_1_tricks = Game.team_1_tricks + 1; | |
cout << *(Game.players.at(2)) << " takes the trick" << endl << endl; | |
} | |
else if(index_highest == 3) | |
{ | |
Game.team_2_tricks = Game.team_2_tricks + 1; | |
cout << *(Game.players.at(3)) << " takes the trick" << endl << endl; | |
} | |
index_winner = index_highest; | |
//end processing of 1 trick | |
} | |
//Requires: player have cards in hand, trump must be chosen | |
//Modifies: stdout, scores | |
//Effects: simulates a round of trick taking | |
void makeTrump(int roundNum, const Card &upcard, int dealer, struct Game &Game) | |
{ | |
//bool orderedUp = false; | |
vector<int> playerIndex; | |
int start_index = eldestHand(dealer); | |
int player_index = 0; | |
bool choice = false; | |
//executes the trump making procedure for all players | |
while(player_index < 4) | |
{ | |
/* | |
//check if player is human | |
if(Game.players.at(start_index)->isHuman()) | |
{ | |
//sorts player's hand | |
Game.players.at(start_index)->sortHand(); | |
} | |
*/ | |
choice = Game.players.at(start_index)->make_trump(upcard, *(Game.players.at(Game.dealer)), roundNum, Game.trump_suit); | |
if(choice == true) | |
{ | |
cout << *(Game.players.at(start_index)) << " orders up " << Game.trump_suit << endl << endl; | |
//if the roudn is 1 bring up dealers hand | |
if(roundNum == 1) | |
{ | |
Game.players.at(Game.dealer)->add_and_discard(upcard); | |
} | |
//determine which team ordered up | |
if(start_index == 0 || start_index == 2) | |
{ | |
Game.team_1_orderUp = true; | |
} | |
else | |
{ | |
Game.team_2_orderUp = true; | |
} | |
return; | |
} | |
else if(choice == false) | |
{ | |
cout << *(Game.players.at(start_index)) << " passes" << endl; | |
} | |
//increment start_index | |
++start_index; | |
if(start_index > 3) | |
{ | |
start_index = 0; | |
} | |
//cout << start_index << endl; | |
//exit loop condition | |
++player_index; | |
//cout << player_index << endl; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// File Name: Card.cpp | |
// By: Ryan Su | |
//uniqname: rysu | |
#include "Pack.h" | |
#include "Card.h" | |
#include <vector> | |
#include <string> | |
#include <iostream> | |
#include <fstream> | |
#include <cassert> | |
#include <cstdlib> | |
using namespace std; | |
//========================================================================== | |
//Helper functions prototypes | |
//========================================================================== | |
/* | |
static string convertSuit(string suit); | |
static string convertRank(string rank); | |
*/ | |
//========================================================================== | |
// Defining the helper functions | |
//========================================================================== | |
/* | |
//Requires: suit needs to be a valid suit, ie "Diamonds, Hearts, Clubs, Spades" | |
//Modifies: nothing | |
//Effects: returns the proper suit naming convention for the class card | |
static string convertSuit(string suit) | |
{ | |
if(suit == "Diamonds") | |
{ | |
return Card::SUIT_DIAMONDS; | |
} | |
else if(suit == "Hearts") | |
{ | |
return Card::SUIT_HEARTS; | |
} | |
else if(suit == "Clubs") | |
{ | |
return Card::SUIT_CLUBS; | |
} | |
return Card::SUIT_SPADES; | |
} | |
//Requires: rank needs to be a valid rank, ie "Two, Three, Four, etc." | |
//Modifies: nothing | |
//Effects: returns the proper rank naming convention for the class card | |
static string convertRank(string rank) | |
{ | |
if(rank == "Two") | |
{ | |
return Card::RANK_TWO; | |
} | |
else if(rank == "Three") | |
{ | |
return Card::RANK_THREE; | |
} | |
else if(rank == "Four") | |
{ | |
return Card::RANK_FOUR; | |
} | |
else if(rank == "Five") | |
{ | |
return Card::RANK_FIVE; | |
} | |
else if(rank == "Six") | |
{ | |
return Card::RANK_SIX; | |
} | |
else if(rank == "Seven") | |
{ | |
return Card::RANK_SEVEN; | |
} | |
else if(rank == "Eight") | |
{ | |
return Card::RANK_EIGHT; | |
} | |
else if(rank == "Nine") | |
{ | |
return Card::RANK_NINE; | |
} | |
else if(rank == "Ten") | |
{ | |
return Card::RANK_TEN; | |
} | |
else if(rank == "Jack") | |
{ | |
return Card::RANK_JACK; | |
} | |
else if(rank == "Queen") | |
{ | |
return Card::RANK_QUEEN; | |
} | |
else if(rank == "King") | |
{ | |
return Card::RANK_KING; | |
} | |
return Card::RANK_ACE; | |
} | |
*/ | |
//========================================================================== | |
// Defining the pack class functions | |
//========================================================================== | |
Pack::Pack() | |
:next(0) {} | |
Pack::Pack(const string &pack_filename) | |
{ | |
//Fill the vector that stores the card | |
string word1; | |
string word2; | |
string word3; | |
ifstream fin; | |
fin.open(pack_filename.c_str()); | |
//a random card to hold values | |
Card cHolder = Card(Card::RANK_TWO, Card::SUIT_SPADES); | |
//if the file cannot be open | |
if(!fin.is_open()) | |
{ | |
cerr << "Error opening " << pack_filename << endl; | |
exit(1); | |
} | |
//fills the card vector | |
else | |
{ | |
while(fin >> word1 >> word2 >> word3) | |
{ | |
//first check if the 2nd word is "of" | |
if(word2 == "of") | |
{ | |
//cHolder will store the card read by the stream | |
cHolder = Card(word1, word3); | |
cards.push_back(cHolder); | |
} | |
} | |
} | |
next = 0; | |
} | |
Card Pack::deal_one() | |
{ | |
assert(next < PACK_SIZE); //check if the pack is empty | |
Card dealtCard = cards.at(next); | |
++next; | |
return dealtCard; | |
} | |
void Pack::reset() | |
{ | |
next = 0; | |
} | |
void Pack::shuffle() | |
{ | |
reset(); | |
vector<Card> firstHalf; | |
vector<Card> secondHalf; | |
int size = 0; | |
int count = 0; | |
//shuffle sequence executes 3 times | |
while(count < 3) | |
{ | |
//clear vecotrs | |
firstHalf.clear(); | |
secondHalf.clear(); | |
//get the cards from 0-16 | |
for(int i = 0; i < 17; ++i) | |
{ | |
firstHalf.push_back(cards.at(i)); | |
} | |
//get the cards from 17-23 | |
for(int i = 17; i < 24; ++i) | |
{ | |
secondHalf.push_back(cards.at(i)); | |
} | |
//clears the cards vector | |
cards.clear(); | |
//fills the cards vector with shuffled cards. | |
size = secondHalf.size(); | |
for(int i = 0; i < size; ++i) | |
{ | |
cards.push_back(secondHalf.at(i)); | |
} | |
size = firstHalf.size(); | |
for(int i = 0; i < size; ++i) | |
{ | |
cards.push_back(firstHalf.at(i)); | |
} | |
++count; | |
} | |
} | |
bool Pack::empty() const | |
{ | |
if(next == PACK_SIZE) | |
{ | |
return true; | |
} | |
return false; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef PACK_H | |
#define PACK_H | |
/* Pack.h | |
* | |
* Represents a pack of playing cards | |
* | |
* by Andrew DeOrio <awdeorio@umich.edu> | |
* 2014-12-21 | |
*/ | |
#include "Card.h" | |
#include <vector> | |
#include <string> | |
class Pack { | |
public: | |
//EFFECTS Creates an empty pack | |
Pack(); | |
//MODIFIES stdout | |
//EFFECTS Initializes Pack by reading from pack_filename. | |
// If file IO fails, prints an error message and calls exit(EXIT_FAILURE). | |
Pack(const std::string &pack_filename); | |
//REQUIRES cards remain in the Pack | |
//EFFECTS Returns the next card in the pack and increments the next pointer | |
Card deal_one(); | |
//EFFECTS Resets next pointer to first card in the Pack | |
void reset(); | |
//EFFECTS Shuffles the Pack and resets the next pointer. See the project | |
// spec for a description of the shuffling procedure | |
void shuffle(); | |
//EFFECTS returns true if there are no more cards left in the pack | |
bool empty() const; | |
private: | |
static const int PACK_SIZE = 24; | |
std::vector<Card> cards; | |
int next; //index of next card to be dealt | |
}; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// File Name: Player.cpp | |
// By: Ryan Su | |
//uniqname: rysu | |
#include "Player.h" | |
#include <string> | |
#include <vector> | |
#include <algorithm> | |
#include <iostream> | |
#include <cassert> | |
using namespace std; | |
//========================================================================== | |
// Simple Player Class | |
//========================================================================== | |
//Class Simple Player | |
class Simple : public Player | |
{ | |
public: | |
Simple(const string name_in) | |
: name(name_in) {} | |
//========================================================================== | |
// Class functions | |
//========================================================================== | |
virtual const string &get_name() const | |
{ | |
return name; | |
} | |
virtual void add_card(const Card &c) | |
{ | |
if(hand.size() <= MAX_HAND_SIZE) | |
{ | |
hand.push_back(c); | |
} | |
} | |
virtual bool make_trump(const Card &upcard, const Player &dealer, | |
int round, string &order_up_suit) const | |
{ | |
//suit of the upcard | |
string upCardSuit = upcard.get_suit(); | |
Card holderCard = Card(hand.at(0).get_rank(), hand.at(0).get_suit()); | |
//round 1 of the simple player | |
if(round == 1) | |
{ | |
//find # of face trump cards. | |
int trumpFaceCount = 0; | |
for(int i = 0; i < MAX_HAND_SIZE; ++i) | |
{ | |
holderCard = hand.at(i); | |
if(holderCard.is_face() && holderCard.is_trump(upCardSuit)) | |
{ | |
++trumpFaceCount; | |
} | |
} | |
// if player has 2 or more trump suit card order up | |
if(trumpFaceCount > 1) | |
{ | |
order_up_suit = upcard.get_suit(); | |
return true; | |
} | |
//pass | |
else | |
{ | |
return false; | |
} | |
} | |
//round 2 of the simple player | |
else if(round == 2) | |
{ | |
if(name == dealer.get_name()) | |
{ | |
//cout << "dealer screw!"<<endl; | |
order_up_suit = Suit_next(upCardSuit); | |
return true; | |
} | |
//find # of face cards of the cross suit | |
int faceCardCount = 0; | |
for(int i = 0; i < MAX_HAND_SIZE; ++i) | |
{ | |
holderCard = hand.at(i); | |
if(holderCard.is_face() && | |
holderCard.get_suit() == Suit_next(upCardSuit)) | |
{ | |
++faceCardCount; | |
} | |
} | |
//order up cross suit if player has 1 or more face card of cross suit | |
if(faceCardCount > 0) | |
{ | |
order_up_suit = Suit_next(upCardSuit); | |
return true; | |
} | |
return false; | |
} | |
return false; | |
} | |
virtual void add_and_discard(const Card &upcard) | |
{ | |
if(hand.size() > 0) | |
{ | |
//"draw" the card | |
hand.push_back(upcard); | |
//discard lowest card including upcard | |
sort(hand.begin(), hand.end()); | |
hand.erase(hand.begin()); | |
} | |
} | |
virtual Card lead_card(const string &trump) | |
{ | |
//check for all trump scenario | |
int handSize = hand.size(); | |
int trumpCount = 0; | |
int index = 0; | |
bool allTrump = false; | |
for(int i = 0; i < handSize; ++i) | |
{ | |
if(hand.at(i).is_trump(trump)) | |
{ | |
++trumpCount; | |
} | |
} | |
//cout << trumpCount << handSize << endl; | |
if(trumpCount == handSize) | |
{ | |
allTrump = true; | |
} | |
Card playCard = Card(hand.at(0).get_rank(), hand.at(0).get_suit()); | |
Card holderCard = Card(hand.at(0).get_rank(), hand.at(0).get_suit()); | |
//if hand is not all trump | |
if(hand.size() > 1 && allTrump == false) | |
{ | |
//find first non-trump suit | |
for(int i = 0; i < handSize; ++i) | |
{ | |
if(hand.at(i).is_trump(trump) == false) | |
{ | |
playCard = hand.at(i); | |
index = i; | |
break; | |
} | |
} | |
//leads with highest non-trump card | |
for(int i = 1; i < handSize; ++i) | |
{ | |
holderCard = hand.at(i); | |
//cout << holderCard << endl; | |
if(holderCard.is_trump(trump) == false && Card_less(playCard, holderCard, trump)) | |
{ | |
playCard = holderCard; | |
//cout << "new: " << playCard << endl; | |
index = i; | |
} | |
} | |
} | |
//if hand is all trump | |
if(hand.size() > 1 && allTrump == true) | |
{ | |
for(int i = 1; i < handSize; ++i) | |
{ | |
holderCard = hand.at(i); | |
if(Card_less(playCard, holderCard, trump)) | |
{ | |
playCard = holderCard; | |
index = i; | |
} | |
} | |
} | |
//remove card | |
holderCard = playCard; | |
hand.erase(hand.begin() + index); | |
return holderCard; | |
} | |
virtual Card play_card(const Card &led_card, const string &trump) | |
{ | |
// check if player can follow suit | |
bool canFollowSuit = false; | |
int handSize = hand.size(); | |
string leadSuit = led_card.get_suit(); | |
Card playCard = Card(hand.at(0).get_rank(), hand.at(0).get_suit()); | |
//cout << "first "<< playCard << endl; | |
int index = 0; | |
for(int i = 0; i < handSize; ++i) | |
{ | |
if((hand.at(i)).get_suit(trump) == leadSuit) | |
{ | |
canFollowSuit = true; | |
//cout << "can follow suit" << endl; | |
} | |
} | |
//follow suit with highest card | |
if(canFollowSuit == true) | |
{ | |
//find the first lead suit card | |
for(int i = 0; i < handSize; ++i) | |
{ | |
if(hand.at(i).get_suit(trump) == leadSuit) | |
{ | |
playCard = hand.at(i); | |
//cout << "Setting to lead suit: " << playCard << endl; | |
index = i; | |
break; | |
} | |
} | |
for(int i = 0; i < handSize; ++i) | |
{ | |
if(Card_less(playCard, hand.at(i), led_card, trump) && | |
hand.at(i).get_suit(trump) == leadSuit) | |
{ | |
playCard = hand.at(i); | |
index = i; | |
} | |
} | |
//cout << "This is the highest led suit: " << playCard << endl; | |
} | |
//if can't follow suit play lowest card | |
else if(canFollowSuit == false) | |
{ | |
playCard = hand.at(0); | |
for(int i = 0; i < handSize; ++i) | |
{ | |
if(Card_less(hand.at(i), playCard, trump)) | |
{ | |
playCard = hand.at(i); | |
index = i; | |
} | |
} | |
} | |
//remove card from hand | |
Card holderCard = playCard; | |
hand.erase(hand.begin() + index); | |
return holderCard; | |
} | |
private: | |
string name; | |
vector<Card> hand; | |
}; | |
//========================================================================== | |
// Human Player Class | |
//========================================================================== | |
//Class Human Player | |
class Human : public Player | |
{ | |
public: | |
Human(const string name_in) | |
: name(name_in) {} | |
//========================================================================== | |
// Defining the helper functions | |
//========================================================================== | |
//Requires: Human class object must be valid and have a hand to print | |
//Modifies: Human class function | |
//Effects: sorts hand vector then prints out hand. | |
void printHand() | |
{ | |
int handSize = hand.size(); | |
//sort hand | |
sort(hand.begin(), hand.end()); | |
//print out the hand | |
for(int i = 0; i < handSize; ++i) | |
{ | |
cout << "Human player " << name << "'s hand: " << "[" << i << "] " << hand.at(i) << endl; | |
} | |
} | |
void sortHand() | |
{ | |
sort(hand.begin(), hand.end()); | |
} | |
//========================================================================== | |
// Class functions | |
//========================================================================== | |
virtual const string &get_name() const | |
{ | |
return name; | |
} | |
virtual void add_card(const Card &c) | |
{ | |
//adds card to player's hand | |
if(hand.size() <= MAX_HAND_SIZE) | |
{ | |
hand.push_back(c); | |
} | |
//sort player hand | |
sortHand(); | |
} | |
virtual bool make_trump(const Card &upcard, const Player &dealer, | |
int round, string &order_up_suit) const | |
{ | |
if(round < 3) | |
{ | |
string playerDecision; | |
//print hand | |
int handSize = hand.size(); | |
//print out the hand | |
for(int i = 0; i < handSize; ++i) | |
{ | |
cout << "Human player " << name << "'s hand: " << "[" << i << "] " << hand.at(i) << endl; | |
} | |
cout << "Human player " << name << ", please enter a suit, or \"pass\":" << endl; | |
cin >> playerDecision; | |
if(playerDecision != "pass") | |
{ | |
order_up_suit = playerDecision; | |
return true; | |
} | |
return false; | |
} | |
//safty false | |
return false; | |
} | |
virtual void add_and_discard(const Card &upcard) | |
{ | |
int playerChoice = 0; | |
printHand(); | |
cout << "Discard upcard: " << "[-1]" << endl; | |
cout << "Human player " << name << ", please select a card to discard:" << endl; | |
cin >> playerChoice; | |
//if player is not discarding upcard | |
if(playerChoice != -1) | |
{ | |
hand.erase(hand.begin() + playerChoice); | |
hand.push_back(upcard); | |
} | |
} | |
virtual Card lead_card(const string &trump) | |
{ | |
int playerChoice = 0; | |
printHand(); | |
cout << "Human player " << name << ", please select a card:" << endl; | |
cin >> playerChoice; | |
Card chosenCard = hand.at(playerChoice); | |
//remove card | |
hand.erase(hand.begin() + playerChoice); | |
return chosenCard; | |
} | |
virtual Card play_card(const Card &led_card, const string &trump) | |
{ | |
int playerChoice = 0; | |
printHand(); | |
cout << "Human player " << name << ", please select a card:" << endl; | |
cin >> playerChoice; | |
Card chosenCard = hand.at(playerChoice); | |
//remove card | |
hand.erase(hand.begin() + playerChoice); | |
return chosenCard; | |
} | |
private: | |
string name; | |
vector<Card> hand; | |
}; | |
Player * Player_factory(const string &name, const string &strategy) | |
{ | |
if(strategy == "Simple") | |
{ | |
return new Simple(name); | |
} | |
else if(strategy == "Human") | |
{ | |
return new Human(name); | |
} | |
//invalid strategy | |
assert(false); | |
exit(1); | |
} | |
ostream &operator<<(ostream &os, const Player &p) | |
{ | |
const string name = p.get_name(); | |
os << name; | |
return os; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef PLAYER_H | |
#define PLAYER_H | |
/* Player.h | |
* | |
* Euchre player interface | |
* | |
* by Andrew DeOrio | |
* awdeorio@umich.edu | |
* 2014-12-21 | |
*/ | |
#include "Card.h" | |
#include <string> | |
#include <vector> | |
class Player { | |
public: | |
//EFFECTS returns player's name | |
virtual const std::string & get_name() const = 0; | |
//REQUIRES player has less than MAX_HAND_SIZE cards | |
//EFFECTS adds Card c to Player's hand | |
virtual void add_card(const Card &c) = 0; | |
//REQUIRES round is 1 or 2 | |
//MODIFIES order_up_suit | |
//EFFECTS If Player wishes to order up a trump suit then return true and | |
// change order_up_suit to desired suit. If Player wishes to pass, then do | |
// not modify order_up_suit and return false. | |
virtual bool make_trump(const Card &upcard, const Player &dealer, | |
int round, std::string &order_up_suit) const = 0; | |
//REQUIRES Player has at least one card | |
//EFFECTS Player adds one card to hand and removes one card from hand. | |
virtual void add_and_discard(const Card &upcard) = 0; | |
//REQUIRES Player has at least one card | |
//EFFECTS Leads one Card from Player's hand according to their strategy | |
// "Lead" means to play the first Card in a trick. The card | |
// is removed the player's hand. | |
virtual Card lead_card(const std::string &trump) = 0; | |
//REQUIRES Player has at least one card | |
//EFFECTS Plays one Card from Player's hand according to their strategy. | |
// The card is removed from the player's hand. | |
virtual Card play_card(const Card &led_card, const std::string &trump) = 0; | |
// Maximum number of cards in a player's hand | |
static const int MAX_HAND_SIZE = 5; | |
// Needed to avoid some compiler errors | |
virtual ~Player() {} | |
}; | |
//EFFECTS: Returns a pointer to a player with the given name and strategy | |
//To create an object that won't go out of scope when the function returns, | |
//use "return new Simple(name)" or "return new Human(name)" | |
//Don't forget to call "delete" on each Player* at the end of Game::play | |
Player * Player_factory(const std::string &name, const std::string &strategy); | |
//EFFECTS: Prints player's name to os | |
std::ostream & operator<<(std::ostream &os, const Player &p); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment