8.1 Design the data structures for a generic deck of cards. Explain how you would subclass the data structures to implement blackjack.
這道題讓我們設計一個21點紙牌遊戲的資料結構,用物件導向的思想來設計。那麼既然21點是一種特定的紙牌遊戲,它可以是從普通紙牌的基礎上派生出來的。所以我們先實現最基本的紙牌類Card,裡面包括值和花色,還有一些基本的判斷或標記可用性的函式。然後就是基本的牌堆類Deck,可以用來加入牌,洗牌,發牌以及算剩餘牌數。還需要一個當前手牌類Hand,可以計算當前分數,可以加牌等。然後就是它們的派生類21點紙牌類BlackJackCard,包括計算值,計算最大最小值,判斷是不是Ace等等,然後就是21點手牌類BlackjackHand,計算當前得分,判斷是否爆了,是否是21點等等。以下程式碼為書上程式碼,有些函式體寫實現,所以暫時無法用具體執行。
// C++ defination enum Suit {Club, Diamond, Heart, Spade}; template<class T> class Deck { public: void setDeckOfCards(vector<T> deckOfCards) {}; // ... void shuffle() {}; // ... int remainingCards() { return _cards.size() - _dealtIndex; } vector<T> dealHead(int number) {}; // ... T dealCard() {}; // ... private: vector<T> _cards; int _dealtIndex = 0; }; class Card { public: Card(int c, Suit s): _faceValue(c), _suit(s) {}; virtual int value() = 0; Suit suit() { return _suit; }; bool isAvailable() { return _available; }; void markUnavailable() { _available = false; }; void markAvailable() { _available = true; }; protected: int _faceValue; Suit _suit; private: bool _available = true; }; template<class T> class Hand { public: int score() { int score = 0; for (T card : cards) { score += card.value(); } return score; } void addCard(T card) { cards.add(card); } protected: vector<T> cards; }; class BlackJackCard: public Card { public: BlackJackCard(int c, Suit s): Card(c,s) {}; int value() { if (isAce()) return 1; else if (_faceValue >= 11 && _faceValue <= 13) return 10; else return _faceValue; } int minValue() { if (isAce()) return 1; else return value(); } int maxValue() { if (isAce()) return 11; else return value(); } bool isAce() { return _faceValue == 1; } bool isFaceCard() { return _faceValue >= 11 && _faceValue <= 13; } }; class BlackjackHand: public Hand<BlackJackCard> { public: int score() { vector<int> scores = possibleScores(); int maxUnder = INT_MIN, minOver = INT_MAX; for (auto a : scores) { if (a > 21 && a < minOver) { minOver = a; } else if (a <= 21 && a > maxUnder) { maxUnder = a; } } return maxUnder == INT_MIN ? minOver : maxUnder; } bool busted() { return score() > 21; }; bool is21() { return score() == 21; }; bool isBlackJack() {}; // ... private: vector<int> possibleScores() {}; // ... };