These are from 9 December. The calendar program that we split up into files to learn about separate compilation is available in calendar.zip. It contains:
Then we also revamped part of our Card structure using a class
, with a “member function” for print()
:
Another example of a struct that overloads the <<
operator is:
Finally, the solution to A11 and a start on the next-generation Poker game for A12 is below.
// cards.cpp -- start of a Poker game!
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
// A playing card is one of 4 suits
const int HEARTS = 0;
const int CLUBS = 1;
const int SPADES = 2;
const int DIAMONDS = 3;
const int NUM_SUITS = 4;
// and 13 ranks (A,2,3,4,5,6,7,8,9,10,J,Q,K)
const int ACE = 1;
const int JACK = 11;
const int QUEEN = 12;
const int KING = 13;
const int NUM_RANKS = 13;
const int NUM_CARDS = NUM_SUITS * NUM_RANKS; // 52
// Define my own type for a playing card
struct Card {
int rank; // these are called FIELDS
int suit;
}; // note semi-colon
// Function prototypes
void create_deck (Card cards[NUM_CARDS]);
void shuffle_deck (Card deck[NUM_CARDS]);
void print_card (Card c);
void print_cards (Card cards[], int start, int how_many);
void tally_ranks (Card hand[], int count, int tally[NUM_RANKS+1]);
void tally_suits (Card hand[], int count, int tally[NUM_SUITS]);
int detect_N_of_a_kind (Card hand[], int count, int n);
int detect_pair (Card hand[], int count);
int detect_three_of_kind(Card hand[], int count);
int detect_four_of_kind (Card hand[], int count);
int detect_full_house (Card hand[], int count);
int detect_flush (Card hand[], int count);
void detect_best_hand (Card hand[], int count);
void test_detector (string name, Card hand[], int count,
int expected, int actualy);
void test_everything ();
/********************************************************
* MAIN PROGRAM *
********************************************************/
int main()
{
//test_everything();
// Initialize the random numbers
long seed = time(NULL);
cout << "Seed is " << seed << "\n";
srand(seed);
// Declare my deck
Card deck[NUM_CARDS];
create_deck(deck);
shuffle_deck(deck);
int top = 48; // the current top of the deck
Card hand[5];
// Deal 5 cards into the player's hand
for(int i = 0; i < 5; i++) {
hand[i] = deck[top]; top = (top+1)%NUM_CARDS;
}
print_cards(hand, 0, 5);
detect_best_hand(hand, 5);
while(1) {
// Ask for discards
cout << "Discard? ";
string discards;
getline(cin, discards);
if(discards == "") break; // game over
for(int i = 0; i < discards.size(); i++) {
if(discards[i] >= 'a' && discards[i] <= 'e') {
int j = discards[i] - 'a';
hand[j] = deck[top]; top = (top+1)%NUM_CARDS;
} else {
cout << "?error you typed '" << discards[i] << "'\n";
}
}
// Show again
print_cards(hand, 0, 5);
detect_best_hand(hand, 5);
}
cout << "GAME OVER, thanks for playing.\n";
return 0;
}
void detect_best_hand(Card hand[], int count)
{
// This should detect in order from best to worst hands.
int p = detect_pair(hand, count);
if(p > 0) {
cout << "You have a pair of " << p << "s\n";
// Above should use "Ace", "Jack", etc. if appropriate
}
else {
cout << "You've got a lot of nothing.\n";
}
}
void test_everything()
{
// Hard-code a particular hand for testing
Card hand[5] = {{3, DIAMONDS},
{3, HEARTS},
{3, SPADES},
{3, CLUBS},
{ACE, SPADES}};
test_detector("four of a kind", hand, 5, 3,
detect_four_of_kind(hand, 5));
hand[2].rank = 2;
test_detector("three of a kind", hand, 5, 3,
detect_three_of_kind(hand, 5));
hand[2].rank = ACE;
test_detector("full house", hand, 5, 3,
detect_full_house(hand, 5));
test_detector("flush", hand, 5, -1,
detect_flush(hand, 5));
hand[0].suit = DIAMONDS; hand[0].rank = 3;
hand[1].suit = DIAMONDS; hand[1].rank = 4;
hand[2].suit = DIAMONDS; hand[2].rank = 5;
hand[3].suit = DIAMONDS; hand[3].rank = 6;
hand[4].suit = DIAMONDS; hand[4].rank = 7;
test_detector("flush", hand, 5, DIAMONDS,
detect_flush(hand, 5));
hand[0].suit = DIAMONDS; hand[0].rank = 7;
hand[1].suit = CLUBS; hand[1].rank = 7;
hand[2].suit = DIAMONDS; hand[2].rank = 5;
hand[3].suit = SPADES; hand[3].rank = 7;
hand[4].suit = CLUBS; hand[4].rank = 8;
test_detector("full house", hand, 5, 0,
detect_full_house(hand, 5));
}
void print_card(Card c)
{
switch(c.rank) {
case ACE: cout << "Ace"; break;
case JACK: cout << "Jack"; break;
case QUEEN: cout << "Queen"; break;
case KING: cout << "King"; break;
default: cout << c.rank; break;
}
cout << " of ";
switch(c.suit) {
case HEARTS: cout << "hearts"; break;
case CLUBS: cout << "clubs"; break;
case SPADES: cout << "spades"; break;
case DIAMONDS: cout << "diamonds"; break;
}
}
void create_deck(Card cards[NUM_CARDS])
{
int i = 0;
for(int s = 0; s < NUM_SUITS; s++)
{
for(int r = 1; r <= NUM_RANKS; r++, i++)
{
cards[i].rank = r;
cards[i].suit = s;
}
}
}
void print_cards(Card deck[NUM_CARDS],
int start, int how_many)
{
for(int i = 0; i < how_many; i++)
{
char c = 'a' + i;
cout << c << ") ";
print_card(deck[start+i]);
cout << "\n";
}
}
void shuffle_deck(Card deck[NUM_CARDS])
{
int i;
for(i = 0; i < 1000; i++) { // # of iterations
// Pick two cards in the deck
int j = rand() % NUM_CARDS;
int k = rand() % NUM_CARDS;
// Swap them
Card c = deck[j];
deck[j] = deck[k];
deck[k] = c;
}
}
void tally_ranks(Card hand[], int count,
int tally[NUM_RANKS+1])
{
for(int i = 0; i < count; i++)
{
tally[hand[i].rank]++;
}
}
void tally_suits(Card hand[], int count,
int tally[NUM_SUITS])
{
for(int i = 0; i < count; i++)
{
tally[hand[i].suit]++;
}
}
int detect_N_of_a_kind(Card hand[], int count, int n)
{
int tally[NUM_RANKS+1] = { 0 };
tally_ranks(hand, count, tally);
// Look through tally for N of a kind
for(int r = 1; r <= NUM_RANKS; r++)
{
if(tally[r] == n) return r; // found N at rank r
}
return 0; // no pair
}
/* Returns 0 if no pair found, otherwise
returns rank of pair. */
int detect_pair(Card hand[], int count)
{
return detect_N_of_a_kind(hand, count, 2);
}
int detect_four_of_kind(Card hand[], int count)
{
return detect_N_of_a_kind(hand, count, 4);
}
int detect_three_of_kind(Card hand[], int count)
{
return detect_N_of_a_kind(hand, count, 3);
}
int detect_full_house(Card hand[], int count)
{
int p = detect_pair(hand, count);
int q = detect_three_of_kind(hand, count);
if(p > 0 && q > 0) {
return q;
}
else {
return 0;
}
}
int detect_flush(Card hand[], int count)
{
int tally[NUM_SUITS] = { 0 };
tally_suits(hand, count, tally);
for(int s = 0; s < NUM_SUITS; s++)
{
if(tally[s] == 5) return s; // found a flush in suit s
}
return -1; // no flush
}
void test_detector(string name, Card hand[], int count,
int expected, int actual)
{
cout << "TEST " << name << ":\n";
print_cards(hand, 0, count);
if(expected == actual) {
cout << " -> SUCCESS: " << actual << "\n";
} else {
cout << " -> FAIL: expected " << expected << ", got "
<< actual << "\n";
}
}