Question: C++ card.hxx code: #ifndef card_hxx_ #define card_hxx_ //=========================================================================== #include #include #include #include #include #include #include //=========================================================================== class card { public: using face_type = char; enum

C++

C++ card.hxx code: #ifndef card_hxx_ #define card_hxx_ //=========================================================================== #include #include #include #include

#include #include #include //=========================================================================== class card { public: using face_type = char;

card.hxx code:

#ifndef card_hxx_

#define card_hxx_

//===========================================================================

#include

#include

#include

#include

#include

#include

#include

//===========================================================================

class card

{

public:

using face_type = char;

enum { invalid=0, ace=1, jack=11, queen=12, king=13 };

enum suit_type : char { club, spade, diamond, heart };

private:

face_type face_;

suit_type suit_;

public:

// default construct invalid card value when face_ == 0...

constexpr card() : face_{} { };

constexpr card(card const&) = default;

constexpr card(card&&) = default;

constexpr card& operator =(card const&) = default;

constexpr card& operator =(card&&) = default;

constexpr card(face_type const& f, suit_type const& s) :

face_{f},

suit_{s}

{

if (!valid())

throw std::domain_error("Invalid card.");

}

constexpr auto operator (card const&) const noexcept = default;

constexpr operator bool() const noexcept

{

return valid();

}

constexpr bool valid() const noexcept

{

return face_

}

constexpr face_type face() const noexcept { return face_; }

constexpr suit_type suit() const noexcept { return suit_; }

constexpr void invalidate() noexcept

{

face_ = invalid;

}

constexpr void set(face_type const& f, suit_type const& s)

{

card tmp(f,s);

swap(tmp);

}

constexpr void swap(card& b) noexcept

{

using std::swap;

swap(face_, b.face_);

swap(suit_, b.suit_);

}

friend std::istream& operator >>(std::istream&, card&);

friend std::ostream& operator

};

inline constexpr auto operator (

card::suit_type const& a,

card::suit_type const& b

) noexcept

{

return

static_cast<:underlying_type_t>>(a)

static_cast<:underlying_type_t>>(b)

;

}

inline constexpr void swap(card& a, card& b) noexcept

{

a.swap(b);

}

//===========================================================================

struct card_faces_begin_t final { };

constexpr card_faces_begin_t card_faces_begin{};

class card_faces

{

private:

card::face_type face_;

public:

constexpr card_faces(card_faces_begin_t const&) noexcept :

face_{card::ace}

{

}

constexpr card_faces(card::face_type const& f = card::king+1) :

face_{f}

{

}

constexpr card_faces(card_faces const&)

noexcept = default;

constexpr card_faces& operator =(

card_faces const&) noexcept = default;

constexpr bool operator ==(card_faces const& b) const

noexcept = default;

constexpr card::face_type const& operator *() const noexcept

{

return face_;

}

// prefix ++

constexpr card_faces& operator ++() noexcept

{

++face_;

return *this;

}

// postfix ++

constexpr card_faces operator ++(int) noexcept

{

card_faces retval(*this);

this->operator ++();

return retval;

}

};

//===========================================================================

struct card_suits_begin_t final { };

constexpr card_suits_begin_t card_suits_begin{};

class card_suits

{

private:

std::optional<:suit_type> suit_;

public:

// default constructor constructs invalid suit...

constexpr card_suits() noexcept :

suit_{}

{

}

constexpr card_suits(card_suits_begin_t const&) noexcept :

suit_{card::club}

{

}

constexpr card_suits(card::suit_type const& s) :

suit_{s}

{

}

constexpr card_suits(card_suits const&) noexcept = default;

constexpr card_suits& operator =(card_suits const&) noexcept = default;

constexpr bool operator ==(card_suits const& b) const

noexcept = default;

constexpr card::suit_type const& operator *() const noexcept

{

return *suit_;

}

// prefix ++

constexpr card_suits& operator ++() noexcept

{

if (suit_)

{

switch (*suit_)

{

case card::club: suit_ = card::spade; break;

case card::spade: suit_ = card::diamond; break;

case card::diamond: suit_ = card::heart; break;

default:

case card::heart: suit_.reset(); break;

}

}

return *this;

}

// postfix ++

constexpr card_suits operator ++(int) noexcept

{

card_suits retval(*this);

this->operator ++();

return retval;

}

};

//===========================================================================

//

// For I/O purposes:

// * a "0" face is an invalid card.

// * a "1" face is a 10.

// * a "A", "J", "Q", or "K" face is the same.

// * otherwise the face is a number between 2 and 9.

// * the suit is one of "H", "D", "C", or "S" representing

// hearts, diamonds, clubs, and spades respectively

// * when read in, the suit or face can be in lower case

// * when written out, the suit or face will always be upper case

//

inline std::istream& operator >>(std::istream& is, card& c)

{

std::istream::sentry s(is);

if (s)

{

// read in card "number"...

char ch;

if (is >> ch) // this can skip whitespace

{

switch (ch)

{

case '0': c.face_ = card::invalid; break;

case 'a':

case 'A': c.face_ = card::ace; break;

case '2': c.face_ = 2; break;

case '3': c.face_ = 3; break;

case '4': c.face_ = 4; break;

case '5': c.face_ = 5; break;

case '6': c.face_ = 6; break;

case '7': c.face_ = 7; break;

case '8': c.face_ = 8; break;

case '9': c.face_ = 9; break;

case '1': c.face_ = 10; break;

case 'j':

case 'J': c.face_ = card::jack; break;

case 'q':

case 'Q': c.face_ = card::queen; break;

case 'k':

case 'K': c.face_ = card::king; break;

default:

is.setstate(std::ios::failbit);

is.unget();

return is;

}

}

// read in card suit...

auto ch2 = is.get();

// i.e., unformatted call to get char so no whitespace is skipped

if (ch2 == std::istream::traits_type::eof())

{

// NOTE: unformatted calls return traits_type::eof() to indicate

// an error. This is like checking for a EOF or -1 error when

// doing file I/O in C.

is.setstate(std::ios::badbit);

return is;

}

switch (static_cast(ch2)) // all is okay... cast to char

{

case 'C': c.suit_ = card::club; break;

case 'S': c.suit_ = card::spade; break;

case 'H': c.suit_ = card::heart; break;

case 'D': c.suit_ = card::diamond; break;

default:

is.setstate(std::ios::badbit); // invalid suit

break;

}

}

return is;

}

inline std::ostream& operator

{

std::ostream::sentry s(os);

if (s)

{

// output number/face...

switch (c.face_)

{

case card::invalid: os

case card::ace: os

case card::jack: os

case card::queen: os

case card::king: os

case 10: os

default: os (c.face_); break;

}

// output suit...

switch (c.suit_)

{

case card::club: os

case card::spade: os

case card::diamond: os

case card::heart: os

}

}

return os;

}

//===========================================================================

#endif // #ifndef card_hxx_

At the top of your a4.cxx, start by writing the following include directives: 1. GE 2 3. #include #include #include #include #include 4. 5. 7. #include "card. hxx" Note, by convention, include files enclosed within are searched for in the compiler's "include" search paths and files enclosed within double quotation marks are searched for relative to the current directory. Although using such won't be leveraged in this assignment, you are to store the deck of cards as well as a "hand" in double-ended queues, i.e., in std::deque variables. Rather than writing std::deque each time you want to say "cards", define a type alias called "cards" that is a synonym for std::deque as follows: 1. using cards = std::deque; (Type aliases and typedefs are the same: both define a name as a synonym for another type. Unlike typedef, however, type aliases (i) can be templated and (ii) are easier to read and write due to their assignment-like syntax.) Outputting cards to std::ostream Given previous assignments and the lectures, by now you should be good at writing std::ostream operator whose constructor arguments are, the ostream and (ii) "" (i.e., a space). Remember to return the std::ostream parameter at the end of the function. While one can use loops, etc. to process each element of a container, simpler code (without any loss of efficiency) can be written by calling the appropriate algorithms. Clearly it is easier to understand and maintain one line of code (i.e., the std::copy() call is one line of code) than multiple lines with variables, test conditions, etc. Generating the Deck of Cards In card.hxx, there are two special classes provided called card_faces and card_suits. The purposes of these classes are to provide an easy way to iterate through all possible card faces and all possible card suits. These two classes are very similar to iterators but since understanding such syntax and operator overloads are new to you, the code for generating a deck of cards is given: 1. 2. 3 cards gen_deck_of_cards () { cards retval; for (card_faces f(card_faces_begin), fEnd; f != fEnd; ++f) for (card_suits s (card_suits_begin), sEnd; s != sEnd; ++s) retval.push_back (card( *f, *s}); return retval; } 5. 6 7. 8. (Place this code in your a4.cxx file.) NOTE: While one could have written the for loops to directly use the "face" values, this would have required hard-coding values in the for loop. Since the suit values are part of an enumeration, the for loop code to loop through all possible suits would have been more complicated. By defining two special "iterator-styled" classes, one can easily obtain all possible values of faces and suits in a way that results is clean, easy-to- understand-and-maintain code. Tip: It is a good idea before proceeding further to add a main(), call this function, and output the cards to verify things are working. At the top of your a4.cxx, start by writing the following include directives: 1. GE 2 3. #include #include #include #include #include 4. 5. 7. #include "card. hxx" Note, by convention, include files enclosed within are searched for in the compiler's "include" search paths and files enclosed within double quotation marks are searched for relative to the current directory. Although using such won't be leveraged in this assignment, you are to store the deck of cards as well as a "hand" in double-ended queues, i.e., in std::deque variables. Rather than writing std::deque each time you want to say "cards", define a type alias called "cards" that is a synonym for std::deque as follows: 1. using cards = std::deque; (Type aliases and typedefs are the same: both define a name as a synonym for another type. Unlike typedef, however, type aliases (i) can be templated and (ii) are easier to read and write due to their assignment-like syntax.) Outputting cards to std::ostream Given previous assignments and the lectures, by now you should be good at writing std::ostream operator whose constructor arguments are, the ostream and (ii) "" (i.e., a space). Remember to return the std::ostream parameter at the end of the function. While one can use loops, etc. to process each element of a container, simpler code (without any loss of efficiency) can be written by calling the appropriate algorithms. Clearly it is easier to understand and maintain one line of code (i.e., the std::copy() call is one line of code) than multiple lines with variables, test conditions, etc. Generating the Deck of Cards In card.hxx, there are two special classes provided called card_faces and card_suits. The purposes of these classes are to provide an easy way to iterate through all possible card faces and all possible card suits. These two classes are very similar to iterators but since understanding such syntax and operator overloads are new to you, the code for generating a deck of cards is given: 1. 2. 3 cards gen_deck_of_cards () { cards retval; for (card_faces f(card_faces_begin), fEnd; f != fEnd; ++f) for (card_suits s (card_suits_begin), sEnd; s != sEnd; ++s) retval.push_back (card( *f, *s}); return retval; } 5. 6 7. 8. (Place this code in your a4.cxx file.) NOTE: While one could have written the for loops to directly use the "face" values, this would have required hard-coding values in the for loop. Since the suit values are part of an enumeration, the for loop code to loop through all possible suits would have been more complicated. By defining two special "iterator-styled" classes, one can easily obtain all possible values of faces and suits in a way that results is clean, easy-to- understand-and-maintain code. Tip: It is a good idea before proceeding further to add a main(), call this function, and output the cards to verify things are working

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!