競技プログラミング風 C++問題集【第15回】
目次
ポーカー:役判定(難易度:★★★☆☆)
引数で与えられたカード配列の役を判定する関数 int checkHand(const vector<Card>& v) を実装しなさい。
ただし、無役は0を、ワンペアは1を、…、ストレートフラッシュは8を返すものとする(テストコードのポーカー役 enum 参照)。
また、Card は一枚のカードを表す構造体で、スート(マーク)とランク(数字)から構成される(テストコードの Card 構造体参照)。
[java]
#include <iostream> // 標準入出力ライブラリ
#include <string>
#include <vector>
using namespace std; // std 名前空間使用
#define DO_TEST(exp) do_test(exp, __LINE__)
void do_test(bool b, int line) {
if( b ) return; // OK
cout << "\nNG at line " << line << "\n";
exit(1);
}
typedef unsigned int uint;
enum { // ポーカー役・スート・ランク定数定義
HIGH_CARD = 0, // 無役
ONE_PAIR, // ワンペア
TWO_PAIR, // ツーペア
THREE_OF_A_KIND, // スリーカード
STRAIGHT, // ストレート
FLUSH, // フラッシュ
FULL_HOUSE, // フルハウス
FOUR_OF_A_KIND, // フォーカード
STRAIGHT_FLUSH, // ストレートフラッシュ
N_KIND_HAND, // 役種類数
SPADES = 0, // スペード
CLUBS,
HEARTS,
DIAMONDS,
N_SUIT, // スート(マーク)種類数
RANK_BLANK = -1,
RANK_2 = 0,
RANK_3, RANK_4, RANK_5, RANK_6,
RANK_7, RANK_8, RANK_9, RANK_10,
RANK_J, RANK_Q, RANK_K, RANK_A,
N_RANK, // 数字種類数
N_CARD = N_SUIT * N_RANK, // 全カード枚数
};
// 1枚のカードを表す構造体(ジョーカーは除く)
struct Card
{
public:
Card(char suit = 0, char rank = -1) : m_suit(suit), m_rank(rank) {}
void print() const { std::cout << toString(); }
void printW() const;
std::string toString() const
{
if( m_suit < 0 || m_suit >= N_SUIT || m_rank < 0 || m_rank >= N_RANK )
return std::string("??");
std::string str(1, "SCHD"[m_suit]);
str += "23456789TJQKA"[m_rank];
return str;
}
int numRank() const { return m_rank + (2-RANK_2); } // A は 14 を返す
bool operator==(const Card &x) const { return m_suit == x.m_suit && m_rank == x.m_rank; }
public:
char m_suit; // スート(マーク)
char m_rank; // 0: 2,… 7: 9, 8:10, 9:J, 10:Q, 11:K, 12:A
};
typedef std::vector<Card> Cards;
int checkHand(const Cards& v) {
// ToDo:
return HIGH_CARD;
}
int main() {
DO_TEST(checkHand(Cards{ {SPADES, RANK_A}, {SPADES, RANK_2}, {CLUBS, RANK_4},
{CLUBS, RANK_6}, {HEARTS, RANK_Q} }) == HIGH_CARD);
DO_TEST(checkHand(Cards{ {SPADES, RANK_7}, {CLUBS, RANK_10}, {DIAMONDS, RANK_6},
{SPADES, RANK_5}, {HEARTS, RANK_8} }) == HIGH_CARD);
DO_TEST(checkHand(Cards{ {SPADES, RANK_Q}, {SPADES, RANK_2}, {CLUBS, RANK_4},
{CLUBS, RANK_6}, {HEARTS, RANK_Q} }) == ONE_PAIR);
DO_TEST(checkHand(Cards{ {SPADES, RANK_Q}, {SPADES, RANK_6}, {CLUBS, RANK_4},
{CLUBS, RANK_6}, {HEARTS, RANK_Q} }) == TWO_PAIR);
DO_TEST(checkHand(Cards{ {SPADES, RANK_J}, {SPADES, RANK_6}, {CLUBS, RANK_J},
{CLUBS, RANK_A}, {HEARTS, RANK_J} }) == THREE_OF_A_KIND);
DO_TEST(checkHand(Cards{ {SPADES, RANK_7}, {CLUBS, RANK_9}, {DIAMONDS, RANK_6},
{SPADES, RANK_5}, {HEARTS, RANK_8} }) == STRAIGHT);
DO_TEST(checkHand(Cards{ {SPADES, RANK_A}, {CLUBS, RANK_2}, {DIAMONDS, RANK_3},
{SPADES, RANK_5}, {HEARTS, RANK_4} }) == STRAIGHT);
DO_TEST(checkHand(Cards{ {SPADES, RANK_Q}, {SPADES, RANK_2}, {SPADES, RANK_4},
{SPADES, RANK_6}, {SPADES, RANK_Q} }) == FLUSH);
DO_TEST(checkHand(Cards{ {SPADES, RANK_Q}, {SPADES, RANK_6}, {CLUBS, RANK_Q},
{CLUBS, RANK_6}, {HEARTS, RANK_Q} }) == FULL_HOUSE);
DO_TEST(checkHand(Cards{ {SPADES, RANK_J}, {SPADES, RANK_6}, {CLUBS, RANK_J},
{DIAMONDS, RANK_J}, {HEARTS, RANK_J} }) == FOUR_OF_A_KIND);
DO_TEST(checkHand(Cards{ {SPADES, RANK_10}, {SPADES, RANK_J}, {SPADES, RANK_Q},
{SPADES, RANK_K}, {SPADES, RANK_A} }) == STRAIGHT_FLUSH);
cout << "\nGood Job!\n";
return 0;
}
[/java]
競技プログラミング風 標準C++ライブラリ入門 連載目次リンク
筆者:津田伸秀 プロフィール:テニス・オセロ・ボードゲーム・パズル類が趣味の年齢不詳のおじさん。 自宅研究員(主席)。vi と C++が好き。迷走中・・・ ボードゲーム・パズル系アプリ開発・リリースしてます。 |