★神経衰弱 勝敗判定★


今回はシーンは1つしか作りませんが、結果シーンにつなげられるよう勝敗判定を作りたいと思います。

複数のシーンで共用しますので「GameData.h」の「CommonData構造体」に変数を追加します。

//-----------------------------------------------------------------------------
// 複数のシーンで共用するデータを構造体にまとめます。
//-----------------------------------------------------------------------------
struct CommonData {

    int m_result;
};

次にゲームが終了したかどうか判定するプログラムを作りましょう。

「Memory.h」を開き、メンバ関数を追加します。

//前方参照
class Card;
class Player;

class Memory {
public:

    Memory();

    ~Memory();

    void Initialize();

    void Shuffle();

    void FaceUp(const POINT &refPoint, Player &refPlayer1, Player &refPlayer2);

    bool IsFinish() const;

    void DrawCard(Engine *pEngine);

    void DrawScore(Engine *pEngine, Player &refPlayer1, Player &refPlayer2) const;

private:

    const int ADJUST_X; //中央に転送するための調整用X座標
    const int ADJUST_Y; //中央に転送するための調整用Y座標

    const int SHUFFLE; //シャッフル回数

    const int RIGHT_LIMIT;  //領域判定用の右端
    const int BOTTOM_LIMIT; //領域判定用の下端

    const int SCORE_DEST_X_PLAYER1; //プレイヤー1のスコア表示左座標
    const int SCORE_DEST_Y_PLAYER1; //プレイヤー1のスコア表示上座標
    const int SCORE_DEST_X_PLAYER2; //プレイヤー2のスコア表示左座標
    const int SCORE_DEST_Y_PLAYER2; //プレイヤー2のスコア表示上座標

    //カードクラス配列用ポインタ
    Card *m_pCard;

    int m_gameStatus; //ゲームステータス

    int m_savePos[2]; //座標保存用

    enum {
        PLAYER1,
        PLAYER2,
    };

    int m_playerTurn; //ターン管理用
};

「Memory.cpp」の「FaceUp関数」の下に関数本体を追加します。

bool Memory::IsFinish() const
{
    const int CARD_MAX = Card::SUIT * Card::NUMBER;

    bool bFinish = true;

    for (int i = 0; i < CARD_MAX; i++) {
        if (m_pCard[i].IsShow()) {
            bFinish = false;
            break;
        }
    }

    return bFinish;
}

1枚でも表示しているカードがあれば、falseを返します。


これだけでシーンを移行してはいけません、まだ勝敗判定が済んでいません。

もう1度「Memory.h」を開いて、勝敗判定用の定数とメンバ関数を追加しましょう。

//前方参照
class Card;
class Player;

class Memory {
public:

    enum {
        PLAYER1_WIN,
        PLAYER2_WIN,
        DRAW,
    };

    Memory();

    ~Memory();

    void Initialize();

    void Shuffle();

    void FaceUp(const POINT &refPoint, Player &refPlayer1, Player &refPlayer2);

    bool IsFinish() const;

    int Result(Player &refPlayer1, Player &refPlayer2) const;

    void DrawCard(Engine *pEngine);

    void DrawScore(Engine *pEngine, Player &refPlayer1, Player &refPlayer2) const;

private:

    const int ADJUST_X; //中央に転送するための調整用X座標
    const int ADJUST_Y; //中央に転送するための調整用Y座標

    const int SHUFFLE; //シャッフル回数

    const int RIGHT_LIMIT;  //領域判定用の右端
    const int BOTTOM_LIMIT; //領域判定用の下端

    const int SCORE_DEST_X_PLAYER1; //プレイヤー1のスコア表示左座標
    const int SCORE_DEST_Y_PLAYER1; //プレイヤー1のスコア表示上座標
    const int SCORE_DEST_X_PLAYER2; //プレイヤー2のスコア表示左座標
    const int SCORE_DEST_Y_PLAYER2; //プレイヤー2のスコア表示上座標

    //カードクラス配列用ポインタ
    Card *m_pCard;

    int m_gameStatus; //ゲームステータス

    int m_savePos[2]; //座標保存用

    enum {
        PLAYER1,
        PLAYER2,
    };

    int m_playerTurn; //ターン管理用
};

「Memory.cpp」を開き、「Result関数」を「IsFinish関数」の下に追加しましょう。

int Memory::Result(Player &refPlayer1, Player &refPlayer2) const
{
    if (refPlayer1 > refPlayer2) {
        return PLAYER1_WIN;
    }
    else {
        if (refPlayer1 == refPlayer2) {
            return DRAW;
        }
        else {
            return PLAYER2_WIN;
        }
    }
}

すでにプレイヤークラスで勝敗判定用に得点を比較するため「>演算子」と「==演算子」のオーバーロードを作っています。

この結果を最初に作った共用データに入れます。


では「IsFinish関数」「Result関数」を踏まえて「SceneGame.cpp」の「Update関数」にコードを追加しましょう。

//=============================================================================
// シーンの実行時に繰り返し呼び出される更新処理関数
//=============================================================================
void SceneGame::Update()
{
    if (m_pEngine->GetMouseButtonSync(DIK_LBUTTON)) {

        POINT point = m_pEngine->GetMousePosition();

        m_memory.FaceUp(point, m_player1, m_player2);
    }

    if (m_memory.IsFinish()) {

        m_gameData.m_result = m_memory.Result(m_player1, m_player2);
        
        m_nowSceneData.Set(Common::SCENE_EXIT, false, NULL);
    }
}

結果シーンで使えるように、共用データに結果を代入しています。

ただし、今回は結果シーンは作りませんので、ゲームを終了させています。

実行して終了する事を確認してください。

※実行画像はありません。


ターンの表示


これで完成!と行きたいところですが、「今どちらのターンなのか」が不明瞭です。

プレイヤー自身が管理しなければならないのは、コンピュータゲームとしては欠陥があります。

そこでターンが分かるように手番のプレイヤーに「☆」を付ける事にします。

「Memory.h」に必要な、メンバ関数や変数、定数を追加します。

//前方参照
class Card;
class Player;

class Memory {
public:

    enum {
        PLAYER1_WIN,
        PLAYER2_WIN,
        DRAW,
    };

    Memory();

    ~Memory();

    void Initialize();

    void Shuffle();

    void FaceUp(const POINT &refPoint, Player &refPlayer1, Player &refPlayer2);

    bool IsFinish() const;

    int Result(Player &refPlayer1, Player &refPlayer2) const;

    void DrawCard(Engine *pEngine);

    void DrawScore(Engine *pEngine, Player &refPlayer1, Player &refPlayer2) const;

    void DrawTurn(Engine *pEngine);

private:

    const int ADJUST_X; //中央に転送するための調整用X座標
    const int ADJUST_Y; //中央に転送するための調整用Y座標

    const int SHUFFLE; //シャッフル回数

    const int RIGHT_LIMIT;  //領域判定用の右端
    const int BOTTOM_LIMIT; //領域判定用の下端

    const int SCORE_DEST_X_PLAYER1; //プレイヤー1のスコア表示左座標
    const int SCORE_DEST_Y_PLAYER1; //プレイヤー1のスコア表示上座標
    const int SCORE_DEST_X_PLAYER2; //プレイヤー2のスコア表示左座標
    const int SCORE_DEST_Y_PLAYER2; //プレイヤー2のスコア表示上座標

    const int STAR_SOUR_X;  //手番用「☆」の転送元左座標
    const int STAR_SOUR_Y;  //転送元上座標
    const int STAR_DEST_X1; //プレイヤー1側の転送先左座標
    const int STAR_DEST_Y1; //転送先上座標
    const int STAR_DEST_X2; //プレイヤー2側の転送先左座標
    const int STAR_DEST_Y2; //転送先上座標
    const int STAR_WIDTH;   //「☆」の幅
    const int STAR_HEIGHT;  //高さ

    //カードクラス配列用ポインタ
    Card *m_pCard;

    int m_gameStatus; //ゲームステータス

    int m_savePos[2]; //座標保存用

    enum {
        PLAYER1,
        PLAYER2,
    };

    int m_playerTurn; //ターン管理用

    RECT m_sour;
    RECT m_dest;
};

「Memory.cpp」を開きましょう。

コンストラクタ関数で定数の初期値を設定します。

Memory::Memory()
    : ADJUST_X(60)
    , ADJUST_Y(120)
    , SHUFFLE(2000)
    , RIGHT_LIMIT(ADJUST_X + Card::NUMBER * Card::SMALL_CARD_WIDTH)
    , BOTTOM_LIMIT(ADJUST_Y + Card::SUIT * Card::SMALL_CARD_HEIGHT)
    , SCORE_DEST_X_PLAYER1(175)
    , SCORE_DEST_Y_PLAYER1(395)
    , SCORE_DEST_X_PLAYER2(495)
    , SCORE_DEST_Y_PLAYER2(395)
    , STAR_SOUR_X(0)
    , STAR_SOUR_Y(1300)
    , STAR_DEST_X1(64)
    , STAR_DEST_Y1(374)
    , STAR_DEST_X2(380)
    , STAR_DEST_Y2(370)
    , STAR_WIDTH(20)
    , STAR_HEIGHT(20)
    , m_pCard(NULL)
{

}

「DrawScore関数」の下に「DrawTurn関数」の本体を追加します。

void Memory::DrawTurn(Engine *pEngine)
{
    SetRect(&m_sour, 
        STAR_SOUR_X, 
        STAR_SOUR_Y, 
        STAR_SOUR_X + STAR_WIDTH, 
        STAR_SOUR_Y + STAR_HEIGHT);

    if (m_playerTurn == PLAYER1) {

        SetRect(&m_dest, 
            STAR_DEST_X1, 
            STAR_DEST_Y1, 
            STAR_DEST_X1 + STAR_WIDTH, 
            STAR_DEST_Y1 + STAR_HEIGHT);
    }
    else {

        SetRect(&m_dest, 
            STAR_DEST_X2,
            STAR_DEST_Y2,
            STAR_DEST_X2 + STAR_WIDTH, 
            STAR_DEST_Y2 + STAR_HEIGHT);
    }

    pEngine->Blt(&m_dest, TEXTURE_TRUMP, &m_sour);
}

最後に「SceneGame.cpp」の「Draw関数」で「DrawTurn関数」を呼び出します。

//=============================================================================
// シーンの実行時に繰り返し呼び出される描画処理関数
//=============================================================================
void SceneGame::Draw()
{
    m_back.Draw(m_pEngine);

    m_memory.DrawCard(m_pEngine);

    m_memory.DrawScore(m_pEngine, m_player1, m_player2);

    m_memory.DrawTurn(m_pEngine);
}

実行して確認しましょう。

<実行結果 クライアント領域のみ>

完成しました!


タイトルシーンや結果シーンは皆さんで追加してみてください。

今回はクラスオブジェクトを使ってゲームを作りましたので、ゲームシーンはすっきりしていると思います。

色々なゲームを通して、クラスを作る事にも慣れていきましょう。


次へ

戻る

目次へ