ポーカー

can110
記事: 27
登録日時: 10年前

ポーカー

投稿記事 by can110 » 9年前

新人研修のネタによさそうだと思い、現実逃避もかねて考えてみたら、意外にはまりました。
http://dixq.net/forum/viewtopic.php?f=3&t=17652

同役の判定が面倒くさい。。。

CODE:

#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;
}

コメントはまだありません。