文系人間がプログラミングをはじめてみた。

プログラミング初心者のゼロからの勉強記録。

マクロで作ったマインスイーパーの解説 詳細編 ゲーム内の操作を行う3

どうもこんにちは。

 

今回もマクロで作ったマインスイーパーのコード解説をしていきます。

どんな感じのマインスイーパーになっているかはこちらからご覧ください。

programminghajimetemita.hatenablog.com

 

今回も前回に引き続きゲーム内の操作に関するコード解説になります。

操作のうち、フラグを設置する処理について紹介しようと思っています。

 

前回までに解説したゲーム内の操作については以下のリンクからご確認ください。

↓はマスを開く処理です。

programminghajimetemita.hatenablog.com

↓はマスを開く処理のうち、空白マスを開いたときの処理です。

programminghajimetemita.hatenablog.com

 

では内容に入ります。

 

 

1.コードの内容

まずはコード全体の内容をご紹介します。

なお、フラグを設置するコードは、前々回で紹介したマスを開く処理を制御するマクロである"operation"の一部として記述しています。

 

2.マインスイーパーの挙動

フラグの設置に関する挙動は前々回の記事でも触れましたが、

ここでもあらためて触れておきます。

 

・未オープンのマスに対してのみフラグを設置することができる

・フラグを設置したマスにはフラグが表示される、

かつ、そのマスの背景色が黄色になる

 

ではコードの内容に入ります。

 

3.コードの内容解説

ユーザーのキー操作で、フラグの設置/解除を行うために必要となるコードです。

このコードにより、"F4キー"が押されたときにThen以下の処理を実行することになります。

 

GetAsyncKeyState関数とはキーボードの状態を取得する関数であり、

このコードを実行すると、カッコ内のキーの状態が数字によって返されます。

キーが押されていないときには"0"が返る仕様ですので、

上記のような条件分岐を組んでおけば、任意のキーが押された(=0でない)ときに、

任意の処理を実行させることが可能になります。

 

詳しくは前々回の記事で解説しておりますので興味があればそちらをご覧ください。

programminghajimetemita.hatenablog.com

 

F4キーを押したときにフラグの設置/解除を行うために必要なコードと理解してもらえればと思います。

 

カーソルの位置にあるマスのセル番地を取得するコードです。

まず、GetCursorPos関数によりカーソルの座標を取得し、

次に、RangeFromPointメソッドによりカーソル座標にあるマスを特定し、

最後にRowプロパティ・Columnプロパティにより特定したマスの行番号・列番号を変数に登録しています。

 

フラグの設置/解除はユーザーが選んだマスに対して行いたいので、

そのマスの位置情報を取得する必要があります。

それを行うのが上記コードというわけです。

 

これらのコードも前々回の記事で詳しく解説していますので、

興味のある方はそちらをご覧ください。

 

ここまでの処理で、F4キーを押したときに、カーソルの場所にあるマスの位置情報を取得することができるようになりました。

以後の処理は、そのマスにフラグを設置する処理、またはそのマスのフラグを解除する処理になります。

では引き続き解説していきます。

 

カーソルの場所にあるマスがオープン済みのマスかを判定する処理です。

2.で触れたとおり、フラグを設置できるのは未オープンのマスだけですので、

まずは特定したマスの内容がオープン済みかどうかを判定しています。

 

オープン済みのマスはそのマスの背景色が灰色(RGB(217,217,217))になっていますので、

特定したマスの背景色がその色でない、という条件を組むことで、

未オープンのマスであるときにThen以下の処理が行われるようにしています。

 

上の条件分岐に引き続き条件分岐を設定しており、

この分岐では特定したマスの値がフラグであるかどうかを判定しています。

 

後ほど解説しますが、フラグを設置する処理ではマスの値をフラグのアイコンにすることによって、

フラグの設置を表現しています。

 

ですので、特定したマスの値がフラグのアイコン(変数icon_fはフラグのアイコンを示す変数です)になっていれば、

すでにフラグを設置していることになりますので、

上記条件分岐を設定してフラグが設置されていないマスに対してのみフラグを設置する処理を行わせるようにしているのです。

 

フラグを設置する処理になります。

先ほど少し触れたように、フラグを設置する処理では、

特定したマスの値を直接フラグのアイコンにすることでフラグ設置を表現しています。

ですので、Valueを使って特定したマスの値をフラグのアイコンに変更しています。

 

NumberFormatLocalで表示形式を変更しているのは、

これをしないと特定したマスの値が画面上見えないので、

画面上フラグが表示されるように表示形式の変更を行っています。

 

2.で触れたとおりフラグのマスの背景色は黄色にする必要があるため、

Interior.ColorIndexの処理により背景色を黄色に変更しています。

 

残りは表示されるフラグのアイコン自体の書式を整える処理です。

Font.ColorIndexでフラグのアイコンを赤色に変更し、

fFont.Nameでフラグの書体を設定しています。

(この書体がマインスイーパーぽいフラグになる書体でしたので、この書体にしています)

 

フラグが設置されたマスからフラグを解除する処理です。

先ほど解説した以下の条件分岐で、特定したマスの値がフラグだったときに行われる処理になります。

 

先ほど述べたように、フラグを設置する処理ではそのマスの値をフラグのアイコンに書き換えています。

つまり、当初爆弾アイコンや数字が値として入力されていたものがフラグに置き換わっているわけです。

ですので、フラグを解除するということは、そのマスの値からフラグを取り除くだけでなく、フラグを設置する前の値に戻してあげる必要があります。

 

それを行うためには、どこか別の場所で初期配置を記憶させておく必要があります。

そうすることで、いつどこでフラグが設置されたとしても、

記憶した初期配置を呼び出すことでフラグ設置前の状態に戻すことが可能になります。

 

では初期配置の記憶をどのような処理でやっているかというと、以下のコードになります。

なお、以下のコードはフラグ設置処理を記述しているマクロで記述しておらず、

マインスイーパーを動かすメインのマクロで記述しています。

この処理によりstart_posは初期配置を示す二次元配列になります。

ここでのポイントは配列として登録するときに.Valueを使って登録することです。

 

このように登録しないと、初期配置が決定された時点で登録を行ったとしても、

事後の値の更新(どこかのマスをフラグにする)が当該配列にも反映されてしまい、

初期の値に戻すことができなくなります。

 

長々と解説してきましたが、以下の2点を押さえていただければOKです。

・初期配置の情報を変数start_posに登録する

・フラグを解除する処理では、変数start_posの情報を利用してフラグ設置前の状態に戻している

 

ではフラグを解除する処理のコードに戻って解説を続けたいと思います。

 

二行目の処理(cnt=~)の部分では変数cntに、フラグ解除マスの元の値を設定しています。爆弾アイコンや数字を入れているわけですね。

これは元の値に戻したときに、その値に応じたフォントの色に戻すために必要な処理になります。

 

先ほどの解説でフラグを設置したときにフォントの色を赤色に変更したと触れました。

そのため、フラグを解除するときにフォントの色に処理を加えないと赤色のままになってしまいます。

 

ここで、元の値の内容(爆弾や数字の種類)によってフォントの色は異なっています。

それらの色の情報はSetNumColor関数で規定していると以前の記事で解説しました。

programminghajimetemita.hatenablog.com

 

SetNumColor関数はcntを引数としているため、cntに元の値を登録したうえで当該関数に連携すれば、

その値に応じたフォント色を返してくれる、というわけです。

ゆえに、二行目のcnt=~の処理を行っています。

 

三行目以下の部分はフラグ設置マスを元の状態に戻す処理になります。

まず、Valueをstart_posの値にすることで、値がフラグアイコンになっていた状態から元の状態に戻ります。

 

Interior.Pattern~Interior.Gradient.ColorStops.Add(1).Colorの部分は背景色を未オープンのマスと同じ状態にする処理です。初期設定にて設定した書式と同じものです。

 

NutmberFormatLocalでは表示形式の変更により、画面上そのマスの値が見えない状態にしています。

フラグ設置によりフラグが見える状態になっていますので、

元の状態に戻す上では当然ながら上記処理によりマスの値を見えなくする必要があります。

 

Font.Nameではフォントの書体を元の書体に戻しています。

こちらもフラグ設置時に書体の変更をしていますので、元に戻す必要があるわけです。

 

最後に、Font.ColorIndexおよびSetNumColor関数により、フォントの色を元の値に応じた色に変更しています。

 

以上でフラグの設置/解除の処理にかかるコード解説を終わります。

 

4.特に重要なコード

3.で解説したコードのうち、特に重要なコードについて振り返りたいと思います。

 

・ユーザーのキーボード操作に応じて任意の処理を実行する

・ユーザーが選んだマスの位置を特定する

上はGetAsyncKeyState関数、下はGetCursorPos関数を利用します。

マスを開く処理と同様、上記処理を行うためにこれらの関数が重要なコードになります。

詳細な解説は前々回の記事で行っていますので、興味のある方はそちらをご覧ください。

 

・設置したフラグを解除する=フラグのアイコンから元の値に戻す

初期配置が完了した時点で、以下のコードにより、変数に初期配置を記録させる

これで、start_pos(r, c)(※r, cは任意の行・列番号)と記述すれば、

(r, c)の位置にある初期配置の値を呼び出すことができます。

 

なお、画面上のマスは左上が(9, 9)の位置から設置されていますが、

start_posに記録された配列では左上が(1,1)として記録されていますので、

呼び出すときの座標に注意が必要です。

(下に記述しているコードで行・列番号をそれぞれ-8しているのはこのためです)

 

上記変数を利用して、フラグ解除の処理時に当該マスの値を元の値に戻す。

 

以上で特に重要なコードの解説を終わります。

 

5.おわりに

今回はゲーム内の操作のうちのフラグ設置・解除部分の処理について解説しました。

次回は経過時間をカウントするマクロについて解説します。

 

ではまた。