设计一副普通纸牌的数据结构,解释如何对其进行子分类以实现特定的纸牌游戏,以及如何对数据结构进行子分类以实现21点。
解决方案:
首先,我们需要认识到,一副“通用”牌可能意味着很多事情。通用可能意味着一副标准的牌,可以玩类似扑克的游戏,甚至可以延伸到Uno或棒球牌。
执行特定的纸牌游戏
假设这副牌是标准的52张牌,就像你在21点或扑克游戏中看到的那样。如果是这样,设计可能如下所示:
这里的结构很清楚:一副牌包含四套西装,一套西装包含13张牌。每张卡片的数值范围为1到13。如果你考虑一个纸牌游戏,不同的游戏不同于发牌和放回纸牌的方式。因此,我们可以在类“Deck”中有一组抽象方法,以允许子类实现自己的处理方式。我画的类图如下:
下面是C++实现的思想。
/*1. Investigation on an individual card instead of a collection of cards, focus on a card's state and interface. 2. A card game has its own specific constrain and requirement on cards, such that a generic card cannot satisfy a blackjack card 3. Player manage multiple cards */ #include <bits/stdc++.h> using namespace std; namespace SUIT { enum Enum { SPADE, HEART, CLUB, DIAMOND }; }; class Card { private : SUIT::Enum s; int v; public : virtual SUIT::Enum suit() const { return s; }; virtual int val() const { return v; }; Card( int val, SUIT::Enum suit) : s(suit), v(val){}; }; class BlackJackCard : public Card { public : virtual int val() { int v = Card::val(); if (v < 10) return v; return 10; } BlackJackCard( int val, SUIT::Enum suit) : Card(val, suit){}; }; class player { private : int id; int bet; set< int > points; vector<BlackJackCard*> bjcs; bool addPoint(set< int >& amp; points, BlackJackCard * card) { if (points.empty()) { points.insert(card->val()); if (card->val() == 1) points.insert(11); } else { /* Set elements are ALWAYS CONST, they can't be modified once inserted. */ set< int > tmp; for ( auto it = points.begin(); it != points.end(); ++it) { tmp.insert(*it + card->val()); if (card->val() == 1) tmp.insert(*it + 11); } points = tmp; } } void getPoints() { cout << "You All Possible Points : " << endl; for ( auto it = points.begin(); it != points.end(); ++it) { cout << *it << endl; } }; int getMinPoints() { /* set is implemented by commonly BST, so else are in order!!! learn to use lower_bound() and upper_bound() "they allow the direct iteration on subsets based on their order." which gives us another option to find min. preferable */ // return *(points.lower_bound(0)); return *(points.begin()); }; void printCards() { cout << "You Cards : " << endl; for ( auto it = bjcs.begin(); it != bjcs.end(); ++it) { cout << (*it)->val() << endl; } } public : player( int i, int j) : id(i), bet(j) { bjcs.push_back( new BlackJackCard( rand () % 13 + 1, SUIT::SPADE)); bjcs.push_back( new BlackJackCard( rand () % 13 + 1, SUIT::SPADE)); addPoint(points, bjcs[0]); addPoint(points, bjcs[1]); }; void getAnotherCard() { for (set< int >::iterator it = points.begin(); it != points.end(); ++it) { /* predefined strategy for the player */ if (*it <= 21 && 21 - *it <= 4) { printCards(); getPoints(); cout << "Stand" << endl; exit (1); } } bjcs.push_back( new BlackJackCard( rand () % 13 + 1, SUIT::SPADE)); addPoint(points, bjcs.back()); if (getMinPoints() > 21) { printCards(); getPoints(); cout << "Busted" << endl; exit (2); } }; virtual ~player() { for ( auto it = bjcs.begin(); it != bjcs.end(); ++it) { delete *it; } }; }; // Driver code int main() { srand ( time (NULL)); player p(1, 1000); p.getAnotherCard(); p.getAnotherCard(); p.getAnotherCard(); return 0; } |
输出:
You Cards : 10 10 You All Possible Points : 20 Stand
实施21点。
注: 现在,假设我们正在构建一个21点游戏,所以我们需要知道这些卡的价值。脸牌是10张,A是11张(大多数情况下,这是手牌课的工作,而不是接下来的课)。
21点游戏开始时,玩家和庄家每人收到两张牌。玩家的牌通常面朝上,而庄家有一张面朝下(称为洞牌),一张面朝上。
最好的21点牌是任何一张10分牌的王牌开局交易。这被称为“21点”,或自然21点,持有该点的玩家自动获胜,除非庄家也有21点。如果一个玩家和庄家都有21点,那么结果就是对该玩家的推动。如果庄家有21点,所有没有持有21点的玩家都会输。
Java中21点的主要逻辑
public class BlackJackHand extends Hand<BlackJackCard> { /* There are multiple possible scores for a blackjack hand, since aces have 3 * multiple values. Return the highest possible score that's under 21, or the 4 * lowest score that's over. */ public int score() { Arraylist<Integer> scores = possibleScores(); int maxUnder = Integer.MIN_VALUE; int minOver = Integer.MAX_VALUE; for ( int score : scores) { if (score > 21 & amp; &score < minOver) { minOver = score; } else if (score <= 21 & amp; &score > maxUnder) { maxUnder = score; } } return maxUnder Integer.MIN_VALUE ? minOver maxUnder; } /* return a list of all possible scores this hand could have (evaluating each * ace as both 1 and 11 */ private Arraylist<Integer> possibleScores() { ... } public boolean busted() { return score() > 21 ; } public boolean is21() { return score() == 21 ; } public boolean isBlackJack() { ... } } public class BlackJackCard extends Card { public BlackJackCard( int c, Suit s) { super (c, s); } public int value() { if (isAce()) return 1 ; else if (faceValue >= 11 & amp; &faceValue <= 13 ) return 10 ; else return faceValue; } public int minValue() { if (isAce()) return 1 ; else return value(); } public int maxValue() { if (isAce()) return 11 ; else return value(); } public boolean isAce() { return faceValue == 1 ; } public boolean isFaceCard() { return faceValue >= 11 & amp; &faceValue <= 13 ; } } /* This is just one way of handling aces. We could, alternatively, create a class of type Ace that extends BlackJackCard. */ |
参考资料: https://www.careercup.com/question?id=2983 http://stackoverflow.com/questions/37363008/a-singleton-class-to-design-a-generic-deck-of-card
本文由 Somesh Awasthi先生 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 贡献极客。组织 或者把你的文章寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。
如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。