Index

HOME > プログラムTOP > C++



DOSポーカー(3)

 ゲームの実行部分である"Poker"クラスの実装コードです。最後に"main"関数を記述していますが、Pokerクラスのインスタンスをつくって、Start関数を呼び出すだけで済みます。

sasaraan programming

Exposition

[6] Player クラスの実装

/**************************************************
	Poker クラス : 実装
**************************************************/

// コンストラクタ
Poker::Poker()
{
    // map の初期化
    g_HandMap[NoPair]          = &g_Hand[0];
    g_HandMap[Pair]              = &g_Hand[1];
    g_HandMap[TwoPair]        = &g_Hand[2];
    g_HandMap[ThreeOfKind]  = &g_Hand[3];
    g_HandMap[Straight]        = &g_Hand[4];
    g_HandMap[Flush]            = &g_Hand[5];
    g_HandMap[FullHouse]      = &g_Hand[6];
    g_HandMap[FourOfKind]    = &g_Hand[7];
    g_HandMap[StraightFlush] = &g_Hand[8];
    g_HandMap[Royal]            = &g_Hand[9];
}

// デストラクタ
Poker::~Poker()
{
}

// リセット
void Poker::Reset()
{
    // タイトル表示
    m_util.MoveCursor(0, 0);
    m_util.InitScreen();
    printf("*********************************\n");
    printf("       DOSポーカー\n");
    printf("*********************************\n\n");
	
    // カードの初期化(-1:配列の終端、99:使用済みカード)
    int i;
    for (i=0; i<52; i++) m_card[i] = i;         // トランプ一組を0から順に初期化
    m_card[52] = -1;                                 // 配列の終端に-1を置く
    for (i=0; i<5; i++) m_mycard[i] = 99;    // 手札5枚を使用済みに設定
    m_mycard[5] = -1;                              // 配列の終端に-1を置く
}

// シャッフル
// ... 引数 *card : トランプ(組)
void Poker::Shuffle(int *card)
{
    srand((unsigned)time(NULL));    // 乱数の初期化

    int i, j, len, temp;
    len = 0;
    while (*(card+len) != -1) len++;    /* 枚数 */
    /* 添え字0のカードから順にランダムに取得した添え字の位置のカードと入れ替え */
    for (i=0; i<len; i++) {
        j = rand() % len;
        temp = card[i];
        card[i] = card[j];
        card[j] = temp;
    }
}

// 交換
// ... 引数 *card : トランプ(組) / ... 引数 *mycard : トランプ(手札)
void Poker::Exchange(int *card, int *mycard)
{
    // 交換した位置には99(交換済みを表す数字)を入れる
    while (*mycard != -1) {
        if (*mycard == 99) {
            if (*card == -1) break;
            while (*card == 99)  card++;
            *mycard = *card;
            *card = 99;
        }
        mycard++;
    }
}

// 並べ替え
// ... 引数 *card : トランプ(組)
void Poker::Sort(int *card)
{
    int len = 0;
    int i, j;
    int temp;

    while (*(card+len)!=-1) len++;    // 枚数
    // 札の数字の小さい順に並べ替え
    for (i=0; i<len-1; i++) {
        for (j=i+1; j<len; j++) {
            if ((card[i]%13)>(card[j]%13)) {
                temp = card[i];
                card[i] = card[j];
                card[j] = temp;
            }
        }
    }
}

// 手役の評価
// ... 引数 *card : トランプ(手札) / .... 戻り値 : 手役データ(Hand構造体)へのポインタ
Hand* Poker::Grading(int *card)
{
    int mark[4];        // マークごとの手札の枚数
    int fig[13];          // 数字ごとの手札の枚数
    int i;
    int temp;
    int fPair = 0;       // ワンペアフラグ
    int fThree = 0;    // スリーカードフラグ

    for (i=0; i<4; i++) mark[i] = 0;  // 各マークを0枚に初期化
    for (i=0; i<13; i++) fig[i] = 0;    // 各数字を0枚に初期化

    // 持ち札のマークと数字を調べて集計
    for (i=0; i<5; i++)  {
        temp = (int)(*(card+i) / 13);
        mark[temp]++;                // マークごとの手札の枚数を集計
        temp = *(card+i) % 13;
        fig[temp]++;                   // 数字ごとの手札の枚数を集計
    }

    // 集計の結果から同じ数字の組み合わせをチェック
    for (i=0; i<13; i++) {
        if (fig[i]==4)  return g_HandMap[FourOfKind];          /* フォーカード */
	
        if (fig[i]==3) {
            if (fPair==1) return g_HandMap[FullHouse];        /* フルハウス */
            else            fThree = 1;
        }
        if (fig[i]==2){
            if (fThree==1)     return g_HandMap[FullHouse];  /* フルハウス */
            else if (fPair==1) return g_HandMap[TwoPair];    /* ツーペア */
            else                   fPair = 1;
        }
    }

    if (fThree) return g_HandMap[ThreeOfKind];               /* スリーカード */
    if (fPair)    return g_HandMap[Pair];                           /* ワンペア */

    int fStraight = 0;        /* ストレートフラグ */
    int fFlush = 0;            /* フラッシュフラグ */

    // フラッシュのチェック
    for (i=0; i<4; i++) {
        if (mark[i]==5) fFlush = 1;
    }

    // ストレートのチェック
    if (fig[0] && fig[9] && fig[10] && fig[11] && fig[12]) {   /* エースハイの場合 */
        if (fFlush)  return g_HandMap[Royal];                   /* ロイヤルストレートフラッシュ */
        fStraight = 1;
    } else {
        for (i=0; i<9; i++) {
            if (fig[i] && fig[i+1] && fig[i+2] && fig[i+3] && fig[i+4])  fStraight = 1;
        }
    }

    if (fFlush && fStraight)  return g_HandMap[StraightFlush];  /* ストレートフラッシュ */
    if (fFlush)     return g_HandMap[Flush];                             /* フラッシュ */
    if (fStraight) return g_HandMap[Straight];                          /* ストレート */
    return g_HandMap[NoPair];                                              /* ノーペア */
}

// 表示
// ... 引数 line : 行番号 / ... 引数 *card : トランプ(組)
void Poker::Show(int line, int *card)
{
    m_util.MoveCursor(0, line);
    printf(" 番号:\n");
    printf(" 手札:\n");

    char mark[5] = "SHDC";    // S:スペード,H:ハート,D:ダイヤ,C:クローバー 
    int  m;                             // 札のマーク
    int  n;                              // 札の数字
    int  i = 0;

    while (*card != -1) {	
        m_util.MoveCursor(i*6+7, line);
        m_util.SetColor();
        printf(" -%d-  ", i+1);
        m_util.MoveCursor(i*6+7, line+1);
        if (*card==99) {        /* 選択済みカードは"*"を表示 */
            m_util.SetColor();
            printf("[ * ] ");
        } else { 
            m = (int)(*card / 13);                             // 札のマーク
            n = *card % 13 + 1;                                // 札の数字
            if (m==0 || m==3) m_util.SetColor(BLUE);  // スペードとクラブは青
            else m_util.SetColor(RED);                      // ハートとダイヤは赤
            printf("[%c%-2d] ", mark[m], n);
        }
        i++;
        card++;
    }
    printf("\n");
    m_util.SetColor();
}

// スタート
int Poker::Start()
{
    string ans;                // ユーザーが入力した文字列
    char req[64];            // ユーザーへの要求を表す文字列
    int res;                    // ユーザー入力から取り出した値
    int paid;                   // 配当金
    int count = 0;           // ゲーム回数
    Hand* hand;             // 手役
    m_money = 10000;    // 持ち金

    // ゲームループ
    while(1) {
        count++;
        Reset();        // 初期化
        do {        /* 掛け金の入力待ち */
            m_util.MoveCursor(0, 4);
            strcpy(req, " 掛け金(持ち金: %d) > ");
            printf(req, m_money);
            getline(cin, ans, '\n');      // 入力文字列の格納
            res = atoi(ans.c_str());     // 値の取り出し
        } while (!(res>0 || res<=m_money));
        m_bet = res;                      // 掛け金
        m_money -= m_bet;            // 持ち金から掛け金を引く

        Shuffle(m_card);                       // シャッフル
        Exchange(m_card, m_mycard);    // カードの配布
        Sort(m_mycard);                      // 並べ替え
        Show(6, m_mycard);                  // 描画
        hand = Grading(m_mycard);        // 手の評価
        printf("\n 手役: %s\n\n",hand->Name);

        while (1) {
            do {        /* カード交換の入力待ち */
                m_util.MoveCursor(0, 10);
                strcpy(req, " 交換するカード(1〜5、9:選択終了) > ");
                printf(req);
                getline(cin, ans, '\n');        // 入力文字列の格納
                res = atoi(ans.c_str());        // 値の取り出し
            } while (!(res>=1 && res<=5 || res==9));
            if (res==9) break;
            m_mycard[res-1] = 99;          // 選ばれたカードを選択済みにする
            printf("\b");                         // 次の入力に備え一文字戻す
            Show(6, m_mycard);               // 対象カードを再描画
        }

        Exchange(m_card, m_mycard);         // カードの交換
        Sort(m_mycard);                           // 並べ替え
        Show(12, m_mycard);                     // 描画
        hand = Grading(m_mycard);             // 手札の評価
        paid = m_bet * hand->Odds;        // 配当金の算出
        m_money += paid;                        // 持ち金の計算
        printf("\n 手役: %s(%d回/全%d回)\n\n",hand->Name, ++hand->Times, count);
        printf(" 配  当: %d×%d=%d\n", m_bet, hand->Odds, paid);
        printf(" 持ち金: %d", m_money);

        if (m_money<=0) break;        // 破産のときはループを抜けてゲーム終了
        do {            /* 続けるかどうかの入力待ち */
            m_util.MoveCursor(0, 20);
            printf(" 1:続ける、2:やめる > ");
            getline(cin, ans, '\n');
            res = atoi(ans.c_str());
        } while (res != 1 && res != 2);
        if (res == 2) break;
    }

    if (m_money<=0){            /* 破産のチェック */
        m_util.SetCursor(0,false);    // カーソルを非表示に
        printf(" 破産です\n");
        ::Sleep(2500);                    // 2.5秒待機してから終了
        m_util.SetCursor();             // カーソルを復帰
    }
    return 0;
} 

[7] main 関数

/**************************************************
    メイン関数
**************************************************/

int main()
{
    Poker m_poker;            // Pokerクラスのインスタンス作成
    ::SetConsoleTitle("DOSポーカー");       // タイトルバー
    m_poker.Start();                                 // ゲーム開始
    return 0;
} 

www.sasaraan.net

(c) morijoh