色当てゲーム(後編)

こんにちは、きうちです。

今日は、前回の 色当てゲーム(前編) の続きをお送りします。

前回までで、問題が出題され、かつそれに解答した後答え合わせをして結果を表示、というところまでできました。

ただ、出題されたものがずっと表示されてしまっていて、ゲームとして成り立っていませんでした。

今回はそこをやります。

★ ★ ★

出題されたら、一瞬それが表示された後、消える。

これを実現するために、タイマーを使用します。

まずは、フィールド変数をちょっと追加。

private System.Windows.Forms.Timer timer = new (); // 出題タイマー

private int wait = 3000; // 解答表示時間

タイマーオブジェクトをフィールド変数 timer でフォームに持たせます。

また、「一瞬」を、具体的に何ミリ秒にするか、をフィールド変数 wait で持たせます。とりあえず3000(=3秒)にしておきます。

そして、このタイマーをセットする処理を SetTimer というメソッドで定義します。

private void SetTimer() // タイマーを設定し、開始させる
{
    timer.Tick += TurnOver; // TICKイベントメソッド設定
    timer.Interval = wait; // インターバル設定
    timer.Start(); // タイマー開始
}

やっていることは「時間がきたらひっくり返す(=非表示にする)」を実行するための手続きです。

Tick には TurnOver というイベントメソッドを紐づけますが、これは次のような内容にします。

private void TurnOver(object? sender, EventArgs e) // ひっくり返す
{
    timer.Stop(); // タイマー停止

    for (int i = 0; i < 4; i++) // 各列について処理
    {
        pictureBoxes[i][0].BackColor = Color.Black; // 上段のピクチャボックスの背景色を黒にする
    }
}

あとでまたTICKしてしまわないように、まずはタイマーを止めます。

そして、4つのピクチャーボックス(出題側、つまり第二インデックスが0)について、バックカラーを黒にします。

そして、出題時に SetTimer を呼ぶようにします(GiveQuestionメソッド)。

private void GiveQuestion()
{
    for(int i = 0; i < 4; i++)
    {
        answer[i] = colors[random.Next(0, 4)];
        pictureBoxes[i][0].BackColor = answer[i];
        pictureBoxes[i][1].BackColor = Color.Black;
    }

    SetTimer(); // (後編追加)タイマー開始
}

ここでいったん、実行してみましょうか。

おお、出題されて3秒後に黒くなりましたね!

★ ★ ★

これで機能するといえばするんですが・・・
問題を出している最中にボタンをポチポチされて回答されるのがヤなので、問題表示中はボタンを押せないようにしましょうか。

そのためにはSetTimerにボタンを非活性にする処理を追加します。

private void SetTimer() // タイマーを設定し、開始させる
{
    EnableButtons(false); // (追加)ボタンを非活性にする

    timer.Tick += TurnOver; // TICKイベントメソッド設定
    timer.Interval = wait; // インターバル設定
    timer.Start(); // タイマー開始
}

ボタンを非活性にする処理は EnableButtons というメソッドで定義し、それを呼ぶことにします。
引数でボタンを活性にするか非活性にするかを指定できるようにします。falseだと非活性です。

EnableButtons はこんな感じにします。

private void EnableButtons(bool sw) // ボタンの活性・非活性を制御する
{
    foreach (var b in Controls) // フォームに存在するコントロール1つ1つについて処理する
    {
        if (b != null && b is Button) // コントロールがNULLでなく、ボタンだったら
        {
            (b as Button).Enabled = sw; // 活性・非活性を設定する
        }
    }
}

フォーム内のボタン全部について処理するような書き方になっています。もちろん、画面の中に非活性になったりしては困るものがある場合はこれではダメなのですが、このゲームでは全て非活性になってしまって構わないので、これで行きます。

また、ひっくり返した後は回答可能にしたいので、次のように TurnOver メソッドに追加します。

private void TurnOver(object? sender, EventArgs e) // ひっくり返す
{
    timer.Stop(); // タイマー停止

    for (int i = 0; i < 4; i++) // 各列について処理
    {
        pictureBoxes[i][0].BackColor = Color.Black; // 上段のピクチャボックスの背景色を黒にする
    }

    EnableButtons(true); // (追加)ボタンを活性にする
}

実行してみます。

問題が消えるまで、ボタンが押せなくなりましたね!

★ ★ ★

これでOKといえばOKですが、どうせなら、クリアするごとに「一瞬」の時間が短くなってほしい。

というわけで、回答ボタン押下時処理をこんな風に変えます。

private void btnAnswer_click(object? sender, EventArgs e)
{
    if (Check())
    {
        for (int i = 0; i < 4; i++)
        {
            pictureBoxes[i][0].BackColor = answer[i];
        }
        MessageBox.Show("正解!");
        wait -= 500;                // (後編追加)待ち時間を500ミリ秒減らす
        if (wait < 500) wait = 500; // (後編追加)待ち時間が500を下回ったら、500にセットしなおす(0とかマイナスになってしまわないように)
        GiveQuestion();
    }
    else
    {
        MessageBox.Show("不正解!");
    }
}

実行してみます。

クリアするごとに問題の表示時間が短くなりましたね!

★ ★ ★

というわけで、今日はここまで。

正解するまでの時間を表示するとか、ステージ番号を表示するなどのようにさらにゲームっぽくするとか、
それによってお友達と競うとか、そういうこともできそうですね。

列数を増やすとか、他にも展開のさせようはありそうです。さらにいじるの、おもしろそうですね!

ではまた次回!

追伸

今回のプログラムを公開しましたので、ご紹介します。↓こちらです。

https://github.com/YasuhikoKiuchi/AnswerColors

★☆ おしらせ ☆★

6月と7月に、迷路を自動生成するプログラムをご紹介しました。

迷路を自動生成してみる(前編)
迷路を自動生成してみる(後編)

が、その全体ソースを公開していませんでした。だいぶ間が空いてしまいましたが公開しましたので当日のブログに追記しました。こちらにもリンクを載せておきます。↓こちら。

https://github.com/YasuhikoKiuchi/Maze

また、改良版を公開しますとお伝えしていましたがなかなか時間が取れず、これもまただいぶ間が空きましたが公開しました!↓こちら。

https://github.com/YasuhikoKiuchi/Maze2

あまりいじれていないですけどね…
気が向いたらまたいじるかもしれないです^^