続いてはゲームのクリア判定を作りましょう。
マインスイーパーは爆弾の個数と開いていないパネルの個数が等しくなったらクリアです。
クリアしたかどうかを判定する関数を追加します。
「Mine.h」を開き、プロトタイプ宣言を書きましょう。
class Mine { public: Mine(); ~Mine(); //フィールドの初期化 void Initialize(const int row, const int col, const int bombMax); //フィールドの描画 void Draw(Engine *pEngine); //パネルを開く bool Open(const POINT &refPoint); //旗を切り替える void SwitchFlag(const POINT &refPoint); //クリアしたか? bool IsClear() const; private: const int ADJUST_X; //調整用左座標 const int ADJUST_Y; //調整用上座標 const int PANEL_SOUR_X; //パネルの転送元左座標 const int PANEL_SOUR_Y; //パネルの転送元上座標 const int HIDE_SOUR_X; //閉じた状態の転送元左座標 const int HIDE_SOUR_Y; //閉じた状態の転送元上座標 const int FLAG_SOUR_X; //旗の転送元左座標 const int FLAG_SOUR_Y; //旗の転送元上座標 const int PANEL_WIDTH; //パネルの幅 const int PANEL_HEIGHT; //パネルの高さ enum { NONE, //爆弾なし BOMB = 9, //爆弾 }; struct Field { int m_number; //周りにある爆弾の数(0〜8)、爆弾は9 bool m_bOpen; //オープンフラグ bool m_bFlag; //旗フラグ }; Field *m_pField; //フィールド int m_row; //縦方向のパネル数 int m_col; //横方向のパネル数 int m_bombMax; //爆弾の最大数 RECT m_sour; RECT m_dest; //フィールドのクリア void ClearField(); //爆弾のセット void SetBomb(); //爆弾の個数のセット void SetNumber(); //周りにある爆弾の数を数える int GetAroundBombNum(const int x, const int y); //フィールド外か? bool IsOutsideField(const POINT &refPoint) const; //隣接したパネルを開く(再帰) void OpenAdjacentPanel(const int x, const int y); }; |
「Mine.cpp」の「SwitchFlag関数」の下に「IsClear関数」の本体を追加しましょう。
//クリアしたか?
bool Mine::IsClear() const
{
const int FIELD_MAX = m_row * m_col;
int counter = 0;
for (int i = 0; i < FIELD_MAX; i++) {
if (!m_pField[i].m_bOpen) {
counter++;
}
}
return counter == m_bombMax;
}
|
開いていないパネルの数を数えて、爆弾の個数と比較した結果を返します。
「SceneGame.cpp」の「Update関数」から呼び出してみます。
//============================================================================= // シーンの実行時に繰り返し呼び出される更新処理関数 //============================================================================= void SceneGame::Update() { if (m_pEngine->GetMouseButtonSync(DIK_LBUTTON)) { POINT point = m_pEngine->GetMousePosition(); if (m_mine.Open(point)) { m_nowSceneData.Set(Common::SCENE_EXIT, false, NULL); } } if (m_pEngine->GetMouseButtonSync(DIK_RBUTTON)) { POINT point = m_pEngine->GetMousePosition(); m_mine.SwitchFlag(point); } if (m_mine.IsClear()) { m_nowSceneData.Set(Common::SCENE_EXIT, false, NULL); } } |
とりあえず、クリアしてもゲームが終了するようにしました。
※今回もシーン切り替えは行いませんが、対応できるように作ります。
実行して、頑張ってクリアしてみてください。
結果を別シーンで使いたい場合を考えておきます。
「GameData.h」の「Common構造体」に変数を追加します。
//-----------------------------------------------------------------------------
// 複数のシーンで共用するデータを構造体にまとめます。
//-----------------------------------------------------------------------------
struct CommonData {
bool m_bClear;
};
|
「SceneGame.cpp」へ戻り、「Update関数」にコードを加えます。
//============================================================================= // シーンの実行時に繰り返し呼び出される更新処理関数 //============================================================================= void SceneGame::Update() { if (m_pEngine->GetMouseButtonSync(DIK_LBUTTON)) { POINT point = m_pEngine->GetMousePosition(); if (m_mine.Open(point)) { m_gameData.m_bClear = false; m_nowSceneData.Set(Common::SCENE_EXIT, false, NULL); } } if (m_pEngine->GetMouseButtonSync(DIK_RBUTTON)) { POINT point = m_pEngine->GetMousePosition(); m_mine.SwitchFlag(point); } if (m_mine.IsClear()) { m_gameData.m_bClear = true; m_nowSceneData.Set(Common::SCENE_EXIT, false, NULL); } } |
これでシーンが変わっても「m_bClear」に結果が入るようになりました。