マクロで作ったマインスイーパーの解説 詳細編 数字を設置する
どうもこんにちは。
今回もマクロで作ったマインスイーパーのコード解説をしていきます。
どんな感じのものになっているかはこちらからご確認ください。
programminghajimetemita.hatenablog.com
今回はマス目に数字を設置する処理について解説したいと思います。
では早速内容に入ります。
1.コードの内容
まずは数字を設置するマクロ全体のコードをご紹介します。
また、このマクロでは各数字に対応するフォント色を返す関数「SetNumColor」を使用していますので、
当該関数のコードも併せて紹介しておきます。
2.マインスイーパーの挙動
コードの内容解説に入る前に、マインスイーパーの挙動について触れておきます。
マインスイーパーでは、各マスに、そのマスの周囲にある爆弾の個数を示す数字が入力されます。
なお、周囲のマスに一つも爆弾がなければそのマスは空白のマスになります。
また、数字ごとにフォント色が決まっており、単に個数を示す数字を入力するだけでなく、
入力した数字のフォント色を塗り分ける必要があります。
マインスイーパーの数字の色を調べると、各数字の色は以下のとおりであったため、
このマクロにおいても当該ルールを踏襲しています。
1:青、2:緑、3:赤、4:紺、5:茶、6:シアン、7:黒、8:灰
以上をまとめると、以下の条件が必要と整理できます。
・各マスに、その周囲のマスにある爆弾の個数を示す数字を入力
・周囲マスの爆弾個数がゼロの場合、空白とする
・入力した数字は規定のフォント色で塗り分ける
ではコードの内容に入っていきたいと思います。
3.コードの内容解説
1.で紹介したコードについて、一つずつ解説していきます。
画面更新を停止するコードです。これは前回の記事でも解説したコードですね。
停止することでマクロの処理速度を向上させています。
最後の行にはこのコードを入れることで画面更新を再開し、
マクロの処理結果を反映させています。
これは繰返処理を行わせるためのコードです。
rは行番号、cは列番号を表しており、
rの方は一番上の行から一番下の行まで、
cの方は一番左の列から一番右の列まで、
繰返処理を行う、という意味になります。
上のコードでは、rの繰返処理の中に、cの繰返処理が重なっているので、
一行目の一番左の列から一番右の列まで処理、
二行目の一番左の列から一番右の列まで処理、
・・・
一番下の行の一番左の列から一番右の列まで処理、
というような繰返処理が行われます。
つまり、このように繰返処理を重ねて使うことで、
すべてのマスに対して同じ処理を行わせることが可能ということです。
数字の設置処理はすべてのマスに対して行う必要があるため、
このコードを採用しています。
数字を入力する対象となるマスの周囲のマスにある爆弾の個数をカウントする処理です。
cntはカウントした爆弾数を記録する変数になります。
"cnt = 0"というコードはcntの値をリセットするために入れているコードになります。
このコードを入れておかないと、繰返処理を行ったときに、
cntの値に前の周回での爆弾の個数が引き継がれてしまい、
次に解説するコードによる処理がうまく行われません。
ですので、繰返処理ごとにcntを一旦ゼロにしてから、
周囲にある爆弾個数に更新するようにしています。
"If・・・"とあるのは、対象のマスが空白であるかどうかをチェックしています。
空白であれば周囲にある爆弾数をカウントし、
そうでなければ処理を終了する、といった処理になっています。
対象のマスが爆弾であれば数字が入る余地がなく、カウントする意味がありませんので、
このような条件分岐としておくことで、対象マスが爆弾のときの処理をスキップさせることができます。
Ifの下の行にあるコードが、周囲のマスにある爆弾数をカウントするコードになります。
カウントにはワークシート関数のCOUNTIF関数を利用しました。
指定の範囲内において、指定条件の値をカウントし、その個数を返す関数です。
範囲の指定はRangeを使って行いました。
(r - 1, c - 1)は対象セルの左上のセルを指し、
(r + 1, c + 1)は対象セルの右下のセルを指します。
このように指定することで、対象セル(r, c)の周囲のマスを範囲指定しています。
検索条件はicon_bということで、爆弾マークを示す変数です。
爆弾設置時は設置対象のマスの値(Value)をicon_bにしていますので、
これを検索条件にすれば、設置された爆弾の個数が返ってくるということになります。
周囲のマスにある爆弾数を対象マスに入力し、入力した数字の色を規定の色に変更する処理です。
まず、cntが1以上かどうかで条件分岐を行っています。
1以上なら処理する、そうでなければ処理しない、となります。
周囲のマスにある爆弾数がゼロの場合は対象マスを空白にする必要がありますので、
爆弾数を対象マスに入力する等の処理はスキップしなければなりません。
そのため、上記のように条件分岐させることで、
爆弾数ゼロの場合に処理をスキップできるようにしています。
なお、先ほど解説したコードで"cnt = 0"というコードがありましたが、
これがないと、ここでのコード実行時にエラーが発生します。
例えば、対象マスが爆弾の場合を考えます。
なお、前回の周回は対象マスに数字"2"を入力したとします。
対象マスは爆弾であり空白マスではないため、
"cnt = WorksheetFunction・・・"部分の処理は行われません。
ここで、cntの値は、"cnt = 0"の処理がありませんので、
前回の周回の値である"cnt = 2"のままです。
cntは"2"のため、cntが1以上の条件を満たし、対象マスに数字を入力する処理が実行されてしまいます。
つまり、本来、対象マスは爆弾であり処理をスキップしたいところなのに、
処理をスキップできないことになる、というわけです。
このエラーを回避するためにも"cnt = 0"の処理が必要ということです。
話を元に戻します。
If・・・の一行下にあるコードが、
周囲のマスにある爆弾数を入力し、入力した数字を規定の色に変更するコードです。
どちらも同じマスに対する処理のため、
Withを使ってマスの指定に関するコード記述を簡略化しています。
爆弾数の入力は"Value"で行います。
cntは先ほど解説した処理によって、周囲のマスにある爆弾数になっていますので、
対象マスの"Value"をcntとすればOKです。
入力した数字の色の変更は"ColorIndex"で行っています。
数字ごとにColorIndexで指定する番号を変えれば、塗分けを行うことができますので、
そのようにコードを記述しました。
数字ごとに指定する番号を変える部分はSetNumColor関数で制御しています。
cntを引数に設定しておき、cntの値によって条件分岐を行わせています。
条件分岐先では、関数が取る値を、各数字の規定の色になるColorIndex番号にしています。
以上、長くなりましたが、数字の入力・色変更の処理部分のコード解説を終わります。
次のコードに移ります。
これはセル番地(1, 1)のセルを選択状態にする処理です。
上記の繰返処理によって一番右下のマスが選択状態になっており、
そのままにしておくと当該マスに入力された値がばれてしまう(数式バーに表示される)ので、
これを回避するために、マス目以外のセルを選択状態にしています。
以上でコードの内容解説を終わります。
4.特に重要なコード
ここまでのおさらいということで、
特に重要なコードについて改めて紹介します。
2.で触れた必要条件別に触れていきます。
・各マスに、その周囲のマスにある爆弾の個数を示す数字を入力
各マスを対象に処理を行わせるのは以下の繰返処理で制御しています。
周囲のマスにある爆弾数のカウントは以下のコードです。
カウントした数字の入力は以下のコードです。
・周囲マスの爆弾個数がゼロの場合、空白とする
周囲のマスにある爆弾数がゼロの場合、処理をスキップすることで、
対象マスの値を空白にしています。
・入力した数字は規定のフォント色で塗り分ける
周囲のマスにある爆弾数(cnt)によって場合分けを行うことで、
数字ごとの色の塗分けを行っています。
5.おわりに
今回は各マスに数字を設置する処理について解説しました。
次回はゲーム内の操作を行う処理について解説しようと思います。
ではまた。