Index

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



DOSポーカー(2)

 ファイルは"dospoker.h"(ヘッダファイル)と"dospoker.cpp"(ソースファイル)の二つをつくります。
 作成するクラスは二つあります。

 1.ConUtil クラス … コンソール画面を制御するクラス
 2.Poker クラス … ゲームの実行に関するクラス

 1 はコンソール画面をクリアしたり、色を変えたりするクラスで、Pokerクラスに組み込んで使用します。2 はゲームのロジックや表示に関するクラスで今回の心臓部となります。こちらの実装部分のコードは (3) に掲載しています。

sasaraan programming

Exposition

[3] 定数と変数の宣言

 stdcolor列挙体では、DOS画面で使うことの出来る16色を定数化し、使いやすくしておきます。つづくHand構造体は、手役に関するデータをまとめたものです。ゲーム中で手役が確定したら、この中のデータを直接出したり入れたりして表示や計算を行うことになります。次のHandKey列挙体は、手役データ(Hand構造体)を呼び出すためのキーです。mapを定義するときに使用します。
"dospoker.h"

#ifndef DOSPOKER_H
#define DOSPOKER_H

#include <windows.h>    // コンソールAPIを使うため
#include <stdio.h>
#include <time.h>         // timeを使うため
#include <iostream>     // cinを使うため
#include <string>          // str型, getlineを使うため
#include <map>            // map型を使うため
using namespace std;

/* stdcolor : 標準16色の定数化 ****************************/

typedef enum stdcolor_tag {
        BLACK, NAVY, GREEN, TEAL, MAROON, PURPLE, OLIVE, SILVER, 
        GRAY, BLUE, LIME, AQUA, RED, FUCHSIA, YELLOW, WHITE,
        } stdcolor;

/* 手役に関する定義 *************************************/

// Hand構造体 : 手役データ
typedef struct {
    char Name[30];        // 表示名称
    int  Odds;                // 配当の倍率
    int  Times;              // 出た回数
} Hand;

// HandKey列挙体 : 手役を呼び出すためのキー
typedef enum {
    NoPair, Pair, TwoPair, ThreeOfKind, Straight, 
    Flush, FullHouse, FourOfKind, StraightFlush, Royal
} HandKey;

// 手役データの初期化 : Hand構造体の配列
Hand g_Hand[] = {
        {"ノーペア",    -1,  0},
        {"ワンペア",      1,  0},
        {"ツーペア",      2,  0},
        {"スリーカード",  5,  0},
        {"ストレート",   10, 0},
        {"フラッシュ",    20, 0},
        {"フルハウス",   30, 0},
        {"フォーカード", 50, 0},
        {"ストレートフラッシュ",  100,  0},
        {"ロイヤルストレートフラッシュ", 500, 0}
};

// 手役データと呼び出しキーの組み合わせ(map)
map<HandKey, Hand*> g_HandMap;

[4] クラスの定義

 "ConUtil" は、コンソール画面にの制御に関するクラスです。標準出力のハンドルを事前に取得しておく必要がありますので、コンストラクタで取得します。逆に使わなくなったときには解放しておかなければなりません。こちらはデストラクタで処理します。
 なお、前景色と背景色の値は保持しておいて、いつでも取り出せるようにしています。
/**************************************************
	ConUtil クラス : 宣言
**************************************************/

// コンソール制御のためのクラス
class ConUtil
{
protected:
    HANDLE m_conout;        // 出力コンソールのハンドル
    stdcolor m_forecolor;     // 前景色
    stdcolor m_backcolor;     // 背景色

public:
    ConUtil();        // コンストラクタ
    ~ConUtil();       // デストラクタ

    void MoveCursor(short col, short row);           // カーソルの位置の設定
    void SetCursor(short size,bool visible);           // カーソルの属性の設定
    void SetColor(stdcolor fore, stdcolor back);    // 色の設定
    void InitScreen();                                    // 現在の設定色で画面をクリア
};
 直接ゲームの実行にかかわる"Poker"クラスの宣言部です。トランプの操作に関する関数のほとんどを内部関数として宣言しています。外部からはコンストラクタとゲームループを呼び出せば済むようになっています。トランプは、0から51までの数字を使って札のマークと札の数字を表現します。
 ・0〜12 … スペードの1から13
 ・13〜25 … ハートの1から13
 ・26〜38 … ダイヤの1から13
 ・39〜51 … クローバーの1から13
 ・-1を配列の終端に使用します
 ・なお、99を交換済みカードの番号として使います
 実装部分のコードは次回掲載します。
/**************************************************
	Poker クラス : 宣言
**************************************************/

// ポーカーの実行クラス
class Poker
{
protected:
    int m_card[53];              // トランプの札
    int m_mycard[6];            // 持ち札
    int m_money;                // 所持金
    int m_bet;                     // 賭け金
    ConUtil m_util;              // コンソールの制御

    void Reset();                            // ゲームのリセット(初期化)
    void Shuffle(int *card);              // トランプのシャッフル
    void Exchange(int *card, int *mycard);    // 札の交換
    void Sort(int *card);                  // トランプの並べ替え
    Hand* Grading(int *card);           // 手札の評価
    void Show(int line, int *card);      // 描画

public:
    Poker();                   // コンストラクタ
    virtual ~Poker();        // デストラクタ
    int Start();               // ゲームループ
};
#endif 

[5] ConUtil クラスの実装

 以下は画面をクリアしたり色を変えたりする"ConUtil"クラスの実装部分です。もともとはWin32APIにある関数です。そのままでは使いづらかったりするので、クラス化して簡略化を試みています。
"dospoker.cpp"

#include "dospoker.h"

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

// コンストラクタ 
ConUtil::ConUtil()
:m_forecolor(SILVER), m_backcolor(BLACK)
{ 
    // コンソール出力ハンドルの取得
    m_conout = ::GetStdHandle(STD_OUTPUT_HANDLE);
}

// デストラクタ
ConUtil::~ConUtil()
{ 
    // コンソール出力ハンドルの開放
    if(m_conout != INVALID_HANDLE_VALUE) ::CloseHandle(m_conout);
}

// カーソルの位置をセットする
// ... 引数col : 列番号
// ... 引数row : 行番号
void ConUtil::MoveCursor(short col, short row)
{
    COORD coord;
    coord.X = col;
    coord.Y = row;
    ::SetConsoleCursorPosition(m_conout, coord);
}

// カーソルのサイズと可視性を設定する 
// ... 引数size  :  カーソルのサイズ(1〜100%)
// ... 引数visible : 可視性
void ConUtil::SetCursor(short size = 25, bool visible = true)
{
    CONSOLE_CURSOR_INFO  info;
    if (size<=0 || size>100) size = 25;
    info.dwSize   = (DWORD)size;
    info.bVisible  = (BOOL)visible;
    ::SetConsoleCursorInfo(m_conout, &info);
}

// 前景色・背景色を設定する
// ... 引数fore : 前景色
// ... 引数back : 背景色 
void ConUtil::SetColor(stdcolor fore = SILVER, stdcolor back = BLACK)
{
    // 前景色・背景色属性を設定
    if (fore>=0 && fore<16) m_forecolor = fore;
    if (back>=0 && back<16) m_backcolor = back;
    ::SetConsoleTextAttribute(m_conout, (WORD)(m_forecolor) + ((WORD)(m_backcolor) << 4));
}

// 現在の設定色で画面を消去する
void ConUtil::InitScreen()
{
    CONSOLE_SCREEN_BUFFER_INFO info; // コンソールスクリーンバッファの情報
    DWORD  charcount;        // 書き込まれたセル数
    COORD  coord = {0, 0};    // 先頭の位置

    if (::GetConsoleScreenBufferInfo(m_conout, &info)) {
        // 現在の範囲に前景色と背景色を設定
        ::FillConsoleOutputAttribute(
                m_conout, 
                m_forecolor + (m_backcolor << 4),
                info.dwSize.X * info.dwSize.Y, 
                coord, 
                &charcount);
        // 現在の範囲に空文字を書き出し
        ::FillConsoleOutputCharacter(
                m_conout, 
                ' ',
                info.dwSize.X * info.dwSize.Y, 
                coord, 
                &charcount);
    }
} 

www.sasaraan.net

(c) morijoh