0

我正在设计一个扑克游戏。将有一个 PokerHand 类用于用户拥有的牌(总是 5 张牌)。PokerHand 有不同的类别,例如顺子、同花顺、满堂彩等。

现在我希望所有的 PokerHand 都具有可比性。类别之间有一个明确的顺序:同花顺 > 同花顺 > 全屋 > ... 对于每个类别,都有不同的比较规则。例如,对于顺子,高牌决定。对于“4 of a kind”,由 4 张相同的牌决定。

class PokerHand {
 public:
  int CompareTo(const PokerHand* another) = 0;
  Category GetCagegory();
 ...
}

使用 RTTI,我可以将 CompareTo 实现为

class Straight : public PokerHand {
  ...
}

int Straight::CompareTo(const PokerHand& another) OVERRIDE {
  const Straight* s = dynamic_cast<const Straight*>(another);
  if (s == NULL) {
    // Not a straight. Compare category.
    ...
  } else {
    // compare high card
    ...
  }
}

现在我的问题是,考虑到 RTTI 主要被视为“不建议使用”,有没有一种不使用 RTTI 来实现比较的好方法?

4

4 回答 4

2

我很确定你这样做的方式是错误的。

APokerHand是 a PokerHand,无论它持有满堂彩、同花顺还是一副完全没用的牌。[如果你用五张牌、七张牌玩扑克,或者显示或不显示你的牌是什么等等,你可能会发现你需要有几种类型——但为了评估你的手牌“价值”,你需要一种班级]。

您需要的是一个可以告诉您实际拥有什么的功能。为此,我将假设您有一个struct Card包含以下内容:

 struct Card
 {
     int suite;  (1..4)
     int value;  (2..14)
 };

然后我假设我们在玩 5 张牌,如果你在玩可变数量的牌,那么你可能想要使用向量。

 class PokerHand
 {
    ... 
    Card cards[5]; 
 }


 int PokerHand::value()     
 // return 0 for "useless, nothing", otherwise how good -> better is higher
 {
    int ret = 0;

    ... check if they are the same suite (flush)
        ... if so, are they in sequence (straight flush)
           ... if so, is the highest a king - (royal straight flush)  
        return ret;

    else

       ... here we write code to check how many cards have the same value 
           (2, 3, 4  of a kind or full house)
       if at least two same value:
       return ret;          

   return ret;

 }

您可能会发现,如果您在两个步骤中分别按套件或按值对牌进行排序,则编写此函数会更容易。您需要考虑牌的价值,例如 3 个 A 击败 3 个 K 击败 3 个 Q 等。您还必须处理“等值,更好的套件”类型的情况,例如 3 个 K,并使用这些值剩余的牌(例如 3 张有两张“未使用的牌”)来确定最高值。

这里列出了规则: http ://en.wikipedia.org/wiki/List_of_poker_hands

于 2013-04-15T07:04:16.670 回答
1

您可以为每种手牌类型分配权重,并为颜色和卡片顺序分配子权重。然后你可以有一个虚函数来计算权重和子权重并比较结果。这对你有用吗?

于 2013-04-15T06:51:19.000 回答
1

尽管它很诱人,但鉴于同花顺、顺子等与扑克手之间的明确关系,我实际上根本不会在这里使用继承,至少对于手型而言不是。例如,在任何平局扑克游戏中,手的类型都可以改变,而在德州扑克等其他游戏中,它只是逐渐显露出来。但是当然类类型在初始化后不能改变。

而是只存储卡片,并有一个返回类型(枚举成员)的基函数或朋友函数,另一个用于排序卡片(这样您就可以获得高卡等)然后定义一个简单的比较器函数,再次为基类或全球朋友,比较两只手。

struct Card
{
   int suit, rank;
};
bool operator<(const Card& a, const Card& b) { ... }

class PokerHand
{
   public: 
      // ... constructor

      enum HandType
      {
         NOTHING = 0,
         PAIR, 
         TWO_PAIR, 
         ...
      }

      HandType GetHandType() { ... }

   private:
      std::vector<Card> _hand;
};
bool operator<(const PokerHand& a, const PokerHand& b) { ... }

填补空白并不难。

如果您确定要派生类,那么我会使用 RTTI 上的类型字段,这可以通过例如上面的枚举来完成。

于 2013-04-15T06:52:02.233 回答
0

那应该很简单。您可以添加某种重量:

class PokerHand {
 public:
  //...
  virtual int GetHandWeights() const = 0;
};

bool operator<( const PokerHand & lh, const PokerHand & rh )
{
  return lh.GetHandWeights() < rh.GetHandWeights();
}

然后,您需要做的就是使用operator<.

于 2013-04-15T06:54:15.733 回答