2013-04-15 100 views
0

我正在设计一个扑克游戏。将有一个PokerHand类用户卡(总是5张卡)。 PokerHand有不同的类别,例如直线,冲洗,满屋等比较没有RTTI的抽象类?

现在我想要所有的PokerHand都是可比的。有一个定义的类别之间的顺序:直冲>一种>满屋> ...对于每个类别都有一个独特的比较规则。例如。对于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?

+0

你可以有一个包含类的虚拟功能,但我想你会了解它的错误的方式......我会写一个答案到那种程度。 –

+0

为各种不同的扑克牌手分别创建一个类似乎是一个糟糕的主意。有很多这样的东西,它们重叠。防爆。皇家同花顺,同花顺,只是简单的冲洗。 – seand

+0

[什么时候应该使用访问者设计模式?](http://stackoverflow.com/questions/255214/when-should-i-use-the-visitor-design-pattern) –

回答

1

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

+0

可能的重复实际上没有任何原因功能是虚拟的。真的只有一种类型的手(目前)。 –

+0

这并不是我得到的印象。你有一个(皇家/直线)冲洗,4种,一个满屋,一对,等等。这些在开场白中是不同的。当然,你可以很容易地做到这一点,但我的答案与“现状”相关。 –

+0

一只手是否是平齐的,或者直的,或者其他什么,不是(或者不应该是)类型的一部分;这是手的价值的函数。只要他将自己的游戏限制在五张牌上,就不需要任何虚拟功能。 –

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

0

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

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

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

然后,您只需使用operator<即可。

2

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

A PokerHand是一个PokerHand,它是否持有满屋,同花顺或一组完全无用的卡。 [你可能会发现,如果你用五张牌,七张牌,或者显示或者不显示你的牌等等来玩扑克,但是为了评估你的手是否“值得”,你需要一种类]。

你需要的是一个函数,可以告诉你实际上有什么。要做到这一点,我会假设你有一个struct Card包含以下内容:

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

那么,我想我们有5张牌打,如果您正在使用的卡的数量可变的玩,那么你probobably想要使用一个矢量。

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种具有两个“未使用的卡”)来确定最高值。

这里有上市规则: http://en.wikipedia.org/wiki/List_of_poker_hands

+0

关于'PokerHand :: value()',我可能会将它作为一系列'if ... else if ... else if ...'来实现,按照rank排序检查每个可能性。它可能不是最有效的(例如,你检查'if(isStraightFlush())'和'if(isFlush())''中的flush,但它似乎是最简单的编写和理解。你也希望返回一个结构体,因为你需要两个元素:手的类型(例如flush,一种三种等等)以及类型中的等级。 –

+0

另一个可能适用继承的地方是:计算类型内的等级。你可以为每种类型设计一个等级计算器。 –

+0

我选择单一返回值的原因是我想要一个简单的比较 - 尽管我想我们总是可以有两个函数,一个返回一个“它是什么”的结构,一个是该类型中的一个等级,然后是第二个可以理解这些等级的功能。是的,一组执行'isFlush()'的函数肯定是一个好主意。 –