比较没有RTTI的抽象类?

时间:2013-04-15 06:43:53

标签: c++ oop design-patterns

我正在设计一款扑克游戏。 PokerHand课程将为用户提供卡片(总是5张卡片)。 PokerHand有不同的类别,例如Straight,Flush,Full House等。

现在我希望所有PokerHand都具有可比性。类别之间有一个明确的顺序:直接冲洗&gt; <4种>满屋子&gt; ...对于每个类别,都有一个不同的比较规则。例如。对于Straights,高牌决定。对于“4种类型”,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 个答案:

答案 0 :(得分:2)

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

PokerHandPokerHand,无论是持有满屋,同花顺还是一套完全无用的牌。 [你可能会发现你需要有几种,如果你玩扑克牌有五张牌,七张牌,或者显示或不显示你的牌等等 - 但是为了评估你的牌“值得”,你需要一个类]。

您需要的是一个可以告诉您实际拥有的功能。为此,我假设你有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 aces beats 3 kings beats 3 queens等。你还必须处理“等值,更好套件”类型的情况,例如: 3个国王,并使用其余卡的值(例如,3种类型有两个“未使用的卡”)来确定最高值。

此处列出了规则: http://en.wikipedia.org/wiki/List_of_poker_hands

答案 1 :(得分:1)

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

答案 2 :(得分:1)

尽管它很明显,但是如果明确的是 - 冲洗,直线等等和扑克手之间的关系,我实际上根本不会使用继承,至少不是手工类型。例如,在任何抽奖扑克游戏中,手牌的类型可以改变,而在其他游戏中,例如Texas Hold-em,它只会逐渐显露出来。但当然,初始化后无法更改类类型。

相反只是存储卡片,并有一个基本或朋友功能,它返回类型(枚举的成员)和另一个用于订购卡片(因此你可以获得高卡等)然后定义一个简单的比较器功能,再次基类或全球朋友,比较两只手。

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上的类型字段,这可以通过例如如上所述的枚举。

答案 3 :(得分:0)

这应该很简单。你可以添加一些重量:

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

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

然后,您只需要使用operator<

相关问题