http://dixq.net/forum/viewtopic.php?f=3&t=17652
同役の判定が面倒くさい。。。
#include
#include
#include
#include
// カード
class Card{
public:
static const int N_SUIT = 4; // マークの種類数
static const int N_RANK =13; // ランクの個数
int m_rank; // ランク 1...13
int m_suit; // マーク 1=S, 2=H, 3=C, 4=D
Card( int rank = 0, int suit = 0):m_rank(rank),m_suit(suit){}
void init( void){ m_rank = 0; m_suit = 0;};
// カードを読込
//
// str : 「HA」など
// card : カードデータ
//
bool read( const char *str){
init();
if( strlen(str) N_SUIT) return false;
// ランク
switch( str[1]){
case 'A': m_rank = 1; break;
case 'J': m_rank = 11; break;
case 'Q': m_rank = 12; break;
case 'K': m_rank = 13; break;
default: m_rank = atoi( &str[1]); break;
}
if( m_rank N_RANK) return false;
return true;
}
};
// 役
class Hand{
public:
// 役ID
enum{ R_NONE = 1, R_1PAIR, R_2PAIR, R_3CARD, R_STRAIT, R_FLUSH, R_FULL, R_4CARD, R_S_FLUSH, R_RS_FLUSH};
static const int N_CARD = 5; // カード枚数
Card m_Card[N_CARD];// 手配カード
int m_val; // 役
int m_sub[N_CARD]; // 同役時の勝敗判定に使用する補足データ
Hand():m_val(0){ init();}
void init( void){
m_val = 0;
memset( m_sub, 0, sizeof(m_sub));
for( int i = 0; i 0){
return false;
}
chk++;
}
return true;
}
// 役の計算
//
// 戻り値 : 役ID R_???
//
int Hand::calcHand( void)
{
m_val = R_NONE;
memset( m_sub, 0, sizeof(m_sub));
// ランクの出現状態の取得とフラッシュ判定
int aCnt[Card::N_RANK+1] = {0}; // 1...13の出現数 [0]は未使用
int maxRank(0); // 出現した最大ランク値
bool isRoyal(false), isFlush(true), isStrait(true);
for( int i = 0; i maxRank) maxRank = cur.m_rank;
}
// ロイヤルストレート判定
if( aCnt[1] == 1 && aCnt[10] == 1 && aCnt[11] == 1 && aCnt[12] == 1 && aCnt[13] == 1){
isRoyal = true;
}
else{
// ストレート判定:最大ランクから降順に1個ずつ出現
for( int i = maxRank; i >= (maxRank - N_CARD + 1); i--){
if( i 1){
if( aCnt[i] > maxSetLen) maxSetLen = aCnt[i];
aSetRank[setCnt] = i;
setCnt++;
}
}
// 高い役から判定
if( isRoyal && isFlush) m_val = R_RS_FLUSH;
else if( isStrait && isFlush) m_val = R_S_FLUSH;
else if( maxSetLen == 4) m_val = R_4CARD;
else if( maxSetLen == 3 && setCnt == 2) m_val = R_FULL;
else if( isFlush) m_val = R_FLUSH;
else if( isRoyal || isStrait) m_val = R_STRAIT; // ロイヤルもストレートとみなしてよい?
else if( maxSetLen == 3) m_val = R_3CARD;
else if( setCnt == 2) m_val = R_2PAIR;
else if( setCnt == 1) m_val = R_1PAIR;
// 同一役の勝敗判定のための補足データ
// ストレート系
if( m_val == R_RS_FLUSH || m_val == R_S_FLUSH || m_val == R_STRAIT){
// 連続するうちの最大ランク値
m_sub[0] = isRoyal ? 1 : maxRank;
}
// 4、3、ワンペア=1セット分
else if( m_val == R_4CARD || m_val == R_3CARD || m_val == R_1PAIR){
// セットのランク値
m_sub[0] = aSetRank[0];
}
// フルハウス=2セット分
else if( m_val == R_FULL){
// スリーカードのランク -> ワンペアのランク
m_sub[0] = aSetRank[ aCnt[aSetRank[0]] == 3 ? 0 : 1];
m_sub[1] = aSetRank[ aCnt[aSetRank[0]] == 3 ? 1 : 0];
}
// 2ペア=2セット分
else if( m_val == R_2PAIR){
// 比較前にエース値を正規化
if( aSetRank[0] == 1) aSetRank[0] = Card::N_RANK+1;
if( aSetRank[1] == 1) aSetRank[1] = Card::N_RANK+1;
// セットのランク値の降順に保持
m_sub[0] = aSetRank[ aSetRank[0] > aSetRank[1] ? 0 : 1];
m_sub[1] = aSetRank[ aSetRank[0] > aSetRank[1] ? 1 : 0];
}
// フラッシュ=最大5つのデータが必要
else if( m_val == R_FLUSH){
// 出現ランク値の降順に保持
// 先頭はエース
int pos(0);
if( aCnt[1] == 1){
m_sub[pos] = 1;
pos++;
}
for( int i = Card::N_RANK; i >= 2; i--){
if( aCnt[i] == 1){
m_sub[pos] = i;
pos++;
}
}
}
// 補足データ中のエース値を正規化
for( int i = 0; i = N_STR) return "???";
return aStr[pos];
}
// 役の比較
//
int compHand( const Hand &h1, const Hand &h2)
{
int cmp = h1.m_val - h2.m_val;
if( cmp) return cmp;
// 同役は最大ランク値などを比較
for( int i = 0; i = 3){
strcpy( aStr[0], argv[1]);
strcpy( aStr[1], argv[2]);
}
else{
// 手配の入力
for( int i = 0; i 0 && aStr[i][len - 1] == '\n') {
aStr[i][len - 1] = '\0';
}
if (strlen(aStr[i]) 0 ? 1 : 2);
return 0;
}