/*
* FreeCell for C.L.I. (Command Line Interface)
*
* File : card.h
* Author : Anupam Srivastava
* E-Mail : anupam.srivastava@gmail.com
* Purpose : C++ header file which defines Card class. It is deliberately
* generic for use with any other program.
*
* NOTE:
* This program is derived from FreeCell for DOS v 1.1 by me. It was for Turbo
* C++ v 3.0, and used custom libraries. Most of such code is removed and aim
* of this program is to just be in standard c++. The original program was not
* throughly checked for bugs.
* Any comments and improvements are invited at anupam.srivastava@gmail.com.
*
* Indentation is left to Vim editor.
*
* LICENSE:
* This program is in public domain. If you find this program helpful in
* anyway, you can send me an email and satisfy my narcissistic needs, thus
* making me happy. ;)
*/
#ifndef _CARD_H
#define _CARD_H 1
#include <string>
#include <sstream>
const int TWO_2 = 2;
const int THREE_3 = 3;
const int FOUR_4 = 4;
const int FIVE_5 = 5;
const int SIX_6 = 6;
const int SEVEN_7 = 7;
const int EIGHT_8 = 8;
const int NINE_9 = 9;
const int TEN_10 = 10;
const int JAILER_11 = 11;
const int QUEEN_12 = 12;
const int KING_13 = 13;
const int ACE_14 = 14;
const char SPADES = 'S';
const char DIAMONDS = 'D';
const char CLUBS = 'C';
const char HEARTS = 'H';
const int INIT_VALUE = 0;
const char INIT_FACE = '\0';
/* Card class represents a playing card with following values:
* TWO_2, THREE_3, FOUR_4, FIVE_5, SIX_6, SEVEN_7, EIGHT_8, NINE_9, TEN_10
* JAILER_11, QUEEN_12, KING_13, ACE_14
* of following suits:
* SPADES, DIAMONDS, CLUBS, HEARTS
*/
class Card {
private:
int value;
char face;
static bool is_valid_value(int card_value);
static bool is_valid_face(char card_face);
public:
Card() : value(INIT_VALUE), face(INIT_FACE) {
}
void reset();
bool set_value(int card_value);
bool set_face(char card_face);
bool set_card(int card_value, char card_face);
bool is_valid();
std::string get_output_string();
int get_value();
int get_face();
bool is_equal_to(Card card);
bool next_small_alternate(Card card2);
bool next_large_same(Card card2);
};
inline
bool Card::is_valid_value(int card_value) {
if (TWO_2 <= card_value && card_value <= ACE_14) {
return true;
}
return false;
}
inline
bool Card::is_valid_face(char card_face) {
switch (card_face) {
case SPADES:
case DIAMONDS:
case CLUBS:
case HEARTS:
return true;
break;
}
return false;
}
inline
void Card::reset() {
value = INIT_VALUE;
face = INIT_FACE;
}
inline
bool Card::set_value(int card_value) {
if (is_valid_value(card_value)) {
value = card_value;
return true;
}
return false;
}
inline
bool Card::set_face(char card_face) {
if (is_valid_face(card_face)) {
face = card_face;
return true;
}
return false;
}
inline
bool Card::set_card(int card_value, char card_face) {
return set_value(card_value) && set_face(card_face);
}
inline
bool Card::is_valid() {
return is_valid_value(value) && is_valid_face(face);
}
std::string Card::get_output_string() {
std::string output = "";
if (is_valid()) {
if (value == TEN_10) {
output = "10";
} else if (value == JAILER_11) {
output = "J";
} else if (value == QUEEN_12) {
output = "Q";
} else if (value == KING_13) {
output = "K";
} else if (value == ACE_14) {
output = "A";
} else {
std::stringstream ss;
ss << value;
output = ss.str();
}
output += face;
}
return output;
}
inline
int Card::get_value() {
return value;
}
inline
int Card::get_face() {
return face;
}
inline
bool Card::is_equal_to(Card card) {
return (value == card.get_value() && face == card.get_face());
}
/* card2 comes after card1 (this)
* but in decreasing order and alternate colour
*/
bool Card::next_small_alternate(Card card2) {
bool card2_is_red = false;
bool card1_is_red = false;
if (card2.get_face() == DIAMONDS || card2.get_face() == HEARTS) {
card2_is_red = true;
}
if (face == DIAMONDS || face == HEARTS) {
card1_is_red = true;
}
/* Either value + 1 of card1 = value of card2
* or value of card1 = ACE_14 and value of card2 = 2
*/
return (card2_is_red != card1_is_red
&& ((card2.get_value() + 1 == value)
|| card2.get_value() - ACE_14 + 2 == value));
}
/* card2 comes after card1 (this)
* but in increasing order
*/
bool Card::next_large_same(Card card2) {
/* Either value + 1 of card1 = value of card2
* or value of card1 = ACE_14 and value of card2 = 2
*/
return (face == card2.get_face()
&& (value + 1 == card2.get_value()
|| value - ACE_14 + 2 == card2.get_value()));
}
#endif /* _CARD_H */