どうも、「○NAKA」です。
ブログを始めたら投稿したいとずっと思っていたことがあります。それは自作したプログラムを投稿することです。今回はみんなが聞いた事がある「モグラ叩きゲーム」をプログラムで実装したので投稿します。
もぐら叩きゲーム
3×3のマスの穴からもぐらがランダムで出現して、そのもぐらを叩く(マウスでクリックする)とスコアがもらえるゲームです。
ゲームの仕様
このゲームの仕様を下記に記載します。ゲームを面白くするために、レアモグラを表示するようにしました。難易度の調整やBGMなどを追加すると更にゲームとして面白くなりそうですが、難しそうなので次回挑戦したいと思います。
[box05 title=”もぐら叩きゲームの仕様”]
- ランダムに通常モグラとレアモグラのどちらか1匹が出現する
- ノーマルもぐらをクリックしたら、10点のスコアがもらえる
- レアもぐらをクリックしたら、30点のスコアがもらえる
- 時間制限を設ける(20秒間)
- 指定秒数毎に出現するもぐらが変わる(指定秒数:1秒)
- 難易度毎にもぐらの出現秒数を変更できる(今回は対象外)
- BGMを追加(今回は対象外)
- マイナスもぐらをクリックしたら、−10点のスコアがもらえる(今回は対象外)
[/box05]
出現したもぐらを叩きたくなるような画像にしたく、1時間ほど探し回っていい感じのイラストを見つけました。白いヘルメットを被っているもぐらが「ノーマルもぐら」で、黄色いヘルメットを被っているもぐらが「レアもぐら」です。もぐらはヘルメットを被っているので、叩いても大丈夫ですよね(笑)。
UI画面の完成イメージ
頭で思い描いているゲーム画面のイメージを具現化するために、エクセルにパパッと書いてみました。3×3のマスと残り時間とスコアの表示、ゲーム開始ボタンがある画面にします。
プログラム実装
- 開発環境:visual studio2019
- 開発プラットフォーム:WPF
- ソリューション名:Whac_A_Mole_GAME
UI画面の作成
まずは、UI画面から作成をします。先程作成した完成イメージを確認しながら、ボタンやラベル、イメージなどのコントロールをサイズ・位置調整をして配置します。下図が完成したUI画面になります。
コード実装
5つの項目に分けてコードの実装をします。
- もぐらの画像をリソースに追加
- タイマー処理
- 出現したもぐらのリセット処理
- もぐらの出現処理
- スコア集計処理
もぐらの画像をリソースに追加
ソリューションエクスプローラーのプロジェクトを右クリックし、「追加」>「新しいフォルダ」をクリックし新規フォルダを作成します。フォルダ名を「Images」に変更します。このフォルダに先ほど見つけたもぐらの画像をドラッグ&ドロップして追加します。フォルダに追加した画像を右クリックしてプロパティを開き、ビルドアクションを「Resource」に変更します。
タイマー処理
Loadedハンドラー内に、タイマーの初期設定を書きます。EventHandlerデリゲートを使用して、タイマーにより呼び出されるメソッド(DispatcherTimer_Tickメソッド)のデリゲートを作成し、TimerクラスのTickイベントに登録します。タイマーメソッドのインターバルは1秒にします。
スタートボタンをクリックした時にタイマーを開始するように、btnStart_Clickメソッドにtimer.Start()を書きます。
public partial class MainWindow : Window
{
private DispatcherTimer timer = new DispatcherTimer();
public MainWindow()
{
InitializeComponent();
Loaded += (s, e) = >
{
timer.Tick += new EventHandler(DispatcherTimer_Tick);
timer.Interval = TimeSpan.FromMinutes(1);
};
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
timer.Start();
}
private void DispatcherTimer_Tick(object sender, EventArgs e)
{
}
}
1秒毎にもぐらを表示した回数をカウントするint型の変数(count)を用意します。
DispatcherTimer_Tickメソッドの先頭にcountをインクリメントする処理とゲーム時間が20秒なので、カウントが20になったらゲームを終了する処理を書きます。ゲーム終了後にもう一度ゲームができるように、btnStart_Clickメソッド内でカウントを0にします。
モグラ叩きゲーム中はスタートボタンをクリックできないように、ボタンのコントロールを無効にします。ゲーム終了後にボタンのコントロールを有効にします。この内容を加えたのが下記になります。
public partial class MainWindow : Window
{
int count = 0;
private DispatcherTimer timer = new DispatcherTimer();
public MainWindow()
{
InitializeComponent();
Loaded += (s, e) =>
{
timer.Tick += new EventHandler(DispatcherTimer_Tick);
timer.Interval = TimeSpan.FromSeconds(1);
};
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
count = 0;
btnStart.IsEnabled = false;
timer.Start();
lblScorebord.Content = "00000";
}
private void DispatcherTimer_Tick(object sender, EventArgs e)
{
count++; //1秒置きにインクリメント
if (count == 20)
{
timer.Stop(); //20秒でゲーム終了
MessageBox.Show("ゲーム終了");
btnStart.IsEnabled = true;
}
else
{
}
}
}
出現したもぐらのリセット処理
もぐらの出現をリセットするメソッドを作成します。3×3のマスで配置したボタンは「btn Mole_番号」、イメージは「ImgMole_番号」で名前を付けています。この名前と一致するボタンとイメージを探して、リセットをする処理を書きます。
private void MoleReset()
{
for (int i = 1; i & amp; lt; 10; i++)
{
//名前からボタンのコントロールを見つける
var btncrl = FindName(string.Format("btnMole_{0}", i));
if (btncrl != null)
{
var btn = (Button)btncrl;
btn.Tag = "";
btn.IsEnabled = false;
}
//名前からイメージのコントロールを見つける
var Imgcrl = FindName(string.Format("ImgMole_{0}", i));
if (Imgcrl != null)
{
var img = (Image)Imgcrl;
img.Source = null;
}
}
}
もぐらの出現処理
次に、もぐらのレア度と出現させる場所に関する処理をまとめたメソッドを作成します。レア度と出現場所は、乱数を使います。C#には乱数を生成するためのRandomクラスが用意されています。Ramdomクラスのランダムコンストラクタでは、乱数系列のシード値を指定することができます。このシード値は指定しましょう。
シード値を指定せずに短時間で複数のRandomクラスのインスタンスを生成すると、同一の乱数系列(乱数の結果が同じになる)が生成されてしまう可能性があります。
もぐらのレア度を乱数の結果から決定します。1~9までの乱数で、1であればレアもぐら、その他の数値であればノーマルもぐらとします。スコアをつけるときに、もぐらの種類がわかるようにボタンのTabにもぐらの種類を記録をしておきます。
次にもぐらの出現場所を乱数の結果から決定します。1~9までの乱数で、3×3のマスに割り当てしているボタン番号と一致する場所にもぐらを出現させます。
private void MoleAppearance()
{
MoleReset();
//シート値を加えてインスタンスを生成する
//モグラの出現場所の乱数
var seed = Convert.ToInt32(Guid.NewGuid().ToString("N").Substring(0, 8), 16);
var appearancePlace = new Random(seed).Next(1, 10);
//モグラのレア度の乱数
seed = Convert.ToInt32(Guid.NewGuid().ToString("N").Substring(0, 8), 16);
var appearanceRarity = new Random(seed).Next(1, 10);
Mole mole = Mole.None;
switch (appearanceRarity)
{
case 1:
mole = Mole.Rare; //レアなモグラ
break;
default:
mole = Mole.Nomal; //通常のモグラ
break;
}
//モグラを表示
var btncrl = FindName(string.Format("btnMole_{0}", appearancePlace));
if (btncrl != null)
{
var btn = (Button)btncrl;
//ボタン許可
btn.Tag = mole;
btn.IsEnabled = true;
//モグラの画像を表示
var Imgcrl = FindName(string.Format("ImgMole_{0}", appearancePlace));
if (Imgcrl != null)
{
var Img = (Image)Imgcrl;
if (Mole.Rare == mole)
{
Img.Source = new BitmapImage(new Uri(@".\Images\レアもぐら.png", UriKind.Relative));
}
else
{
Img.Source = new BitmapImage(new Uri(@".\Images\ノーマルもぐら.png", UriKind.Relative));
}
}
}
}
スコア集計処理
最後にスコアの集計メソッドを作成します。もぐらが表示されたボタンをクリックしたときにスコアが表示されるので、ボタンにクリックイベントを登録します。クリックイベントの処理はどのボタンでも同じなので、メソッド名は統一します。もぐらの種類によってもらえるスコアが違うので、ボタンのTabに記録しているもぐらの種類によってスコアを変えます。
private void btnMole_Click(object sender, RoutedEventArgs e)
{
Button btn = (Button)sender;
btn.IsEnabled = false;
int score = int.Parse((string)lblScorebord.Content);
switch (btn.Tag)
{
case Mole.Rare:
score += 30;
break;
case Mole.Nomal:
score += 10;
break;
}
lblScorebord.Content = score.ToString();
}
アプリケーションの起動
さっそく、作成したアプリケーションを起動してみましょう。スタートボタンをクリックすると、もぐらが1秒間隔で出現します。もぐらをクリックすると、もぐらの種類によってスコアが加算されます。仕様通りの動作をしていることが確認できましたので、今回はこれで終了にします。
次回は、対象外だった仕様について実装をしたいと思います。
以上、最後までご覧いただきありがとうございました。