2013-04-15 2 views
0

저는 포커 게임을 디자인하고 있습니다. 사용자가 가지고있는 카드 (항상 5 장의 카드)를위한 PokerHand 클래스가 있습니다. PokerHand는 다른 카테고리를 가지고 있습니다. Straight, Flush, Full House 등RTTI없이 추상 클래스 비교?

이제 모든 PokerHand를 비교해보고 싶습니다. 카테고리간에 정의 된 순서가 있습니다. 직선 플러시> 4 종류> 풀 하우스> ... 각 카테고리에 대해 비교를위한 뚜렷한 규칙이 있습니다. 예 : 스트레이트의 경우 높은 카드가 결정됩니다. "4 종류"의 경우 4 장의 동일한 카드가 결정됩니다.

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

, 나는 내 질문은, RTTI가 대부분 "를 사용하는 것이 좋습니다 없다"으로 간주됩니다 고려하고 이제

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 
    ... 
    } 
} 

로 compareTo와를 구현할 수는없는 비교를 구현하는 좋은 방법이있다 RTTI를 사용하고 있습니까?

+0

당신은 범주를 포함하는 가상 함수를 가질 수있다,하지만 난 당신이 그것에 대해 잘못된 길을 가고 있다고 생각 ... 그리고 내가 그 정도에 대한 답을 쓸 것이다 . –

+0

다양한 포커 손마다 각각 다른 클래스를 만드는 것은 좋지 않은 생각처럼 들립니다. 이들 중 상당수가 중복되어 있습니다. 전의. 로얄 플러시, 스트레이트 플러시, 그냥 플러시. – seand

+0

가능한 복제본 [언제 방문자 디자인 패턴을 사용해야합니까?] (http://stackoverflow.com/questions/255214/when-should-i-use-the-visitor-design-pattern) –

답변

1

각 손 유형과 하위 가중치에 색상과 카드 순서를 할당 할 수 있습니다. 그런 다음 가중치와 하위 가중치를 계산하고 결과를 비교하는 가상 함수를 가질 수 있습니다. 그게 너에게 도움이 되겠니?

+0

실제로 어떤 이유도 없습니다 함수가 가상 일 것입니다. 실제로는 한 종류의 손만 있습니다 (잠시 동안). –

+0

그게 내가 가진 인상이 아니야. 당신은 (로얄/스트레이트) 플러시, 4 종류, 풀 하우스, 페어 등을 가지고 있습니다. 이것들은 오프닝 질문에서 다른 손입니다. 당연히 당신은 쉽게 그것을하지 않고 도망 갈 수 있지만, 내 대답은 "있는 그대로"의 상태와 관련이 있습니다. –

+0

핸드가 플러시인지, 스트레이트인지, 또는 무엇이든 유형의 일부가 아니거나 또는 일부일 수 없습니다. 이것은 손의 가치의 함수입니다. 자신의 게임을 5 장의 카드로 제한하는 한 가상 기능이 필요하지 않습니다. –

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를 통해 유형 필드로 이동합니다. 위와 같은 enum.

0

매우 간단해야합니다. 어떤 종류의 무게를 추가 할 수 있습니다 :

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

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

그런 다음 operator<을 사용하려면이 작업을 수행해야합니다.

2

나는 당신이 잘못하고있는 방식이 틀림 없음을 확신합니다.

PokerHand은 풀 하우스, 스트레이트 플러시 또는 완전히 쓸모없는 카드 세트를 보유 하든지 상관없이 PokerHand입니다. [5 장의 카드, 7 장의 카드 또는 7 장의 카드로 포커를하거나 여러 장의 카드가 보이거나 보이지 않는 경우 여러 종류가 있어야 할 필요가 있습니다.하지만 손이 "가치가있는 것"을 평가하려면 수업].

필요한 것은 실제로 갖고있는 것을 알 수있는 기능입니다. 당신이 카드의 변수 번호를 재생하는 경우

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

내가, 우리가 5 개 카드와 함께 연주하는 가정, 당신은 probobably :이를 위해, 나는 다음과 같은 포함하는 struct Card가 있다고 가정하겠습니다 벡터를 사용하고 싶다.

두 단계에 대해 각각 스위트 또는 값으로 손을 정렬하면이 기능을 쉽게 작성할 수 있습니다. 카드의 가치를 고려해야합니다 (예 : 3 개의 에이스는 3 개의 왕을 이긴다. 3 개의 왕은 3 개의 왕을 이기고, 등등. 3 킹 카드를 사용하고 나머지 카드 (예 : 3 종류의 카드는 2 개의 "사용하지 않은 카드"를 가짐)의 값을 사용하여 최대 값을 결정합니다.

가 여기에 나열된 규칙입니다 : 가 http://en.wikipedia.org/wiki/List_of_poker_hands

+0

'PokerHand :: value()'에 관해서는'if ... else if ... else if ...'의 순서로 구현할 것이고, 순위의 순서대로 각 가능성을 체크 할 것입니다. 가장 효율적이지는 않을 수도 있습니다 (예 :'if (isStraightFlush())'와'if (isFlush())'둘 다에서 flush를 체크합니다), 쓰고 이해하는 것이 가장 간단합니다. 구조체를 반환하려면 손의 유형 (예 : flush, 3 가지 종류 등)과 유형 내의 순위라는 두 가지 요소가 필요하기 때문입니다. –

+0

그리고 상속이 적절할 수있는 장소 : 유형 내의 순위 계산. 각 유형별 순위 계산기를 사용할 수 있습니다. –

+0

단일 반환 값을 선택하는 이유는 간단한 비교가 필요했기 때문입니다. 우리는 항상 "무엇인가"의 구조체를 반환하는 함수와 해당 형식 내의 순위를 반환하는 두 개의 함수를 가질 수 있다고 생각합니다. 이들 중 순위를 이해하는 함수. 예, isFlush()를하는 함수 세트 등은 확실히 좋은 아이디어입니다. –