Skip to content

Instantly share code, notes, and snippets.

@rysu94

rysu94/Card.cpp Secret

Last active July 14, 2016 20:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rysu94/f1cb887d5dbedbe72f9a81710a901f3e to your computer and use it in GitHub Desktop.
Save rysu94/f1cb887d5dbedbe72f9a81710a901f3e to your computer and use it in GitHub Desktop.
C++ code for a Euchre card game simulator including rudimentary AI
// 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;
}
}
#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
// 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;
}
}
// 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;
}
#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
// 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;
}
#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