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

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

VBAテトリス 詳細編 テトリミノを操作する2

どうもこんにちは。

 

マクロで作ったテトリスの解説記事です。

今回は前回の内容の続きで「テトリミノを操作する」処理についてです。

前回の内容は以下リンクからご参照ください。

programminghajimetemita.hatenablog.com

 

前回の記事では、テトリミノを移動させたり、回転させる処理を行うコードについて解説しました。

ただ、紹介したコードではブロックや壁を無視して移動や回転ができてしまうので、

移動や回転ができる範囲を制限する必要があります。

 

では、移動や回転ができる範囲を制限するにはどういったコードを準備すればよいでしょうか?

今回の記事では、そのあたりを中心に解説していきたいと思います。

 

 

1.テトリミノが落下する処理を振り返る

テトリミノの移動等を制限する処理ですが、実は以前にその内容を紹介しています。

いつ紹介したかというと、テトリミノが落下する処理を紹介したときです。

テトリミノを落下させるにあたり、あらかじめ下に進めるかどうかをチェックする必要があり、

そのためにどのようなコードが必要かを解説しました。

その時の記事はこちらです。

programminghajimetemita.hatenablog.com

 

具体的にどのような処理を行ったかと言いますと、

"テトリミノの一行下の範囲が無色になっているか"、を判定する処理を行いました。

以下のイメージの赤色の範囲が無色かどうかチェックするということです。

 

移動や回転に関しても、上記と同様に、

移動先や回転によってブロックが移動する先が空白になっているか、

をチェックしてやればOKです。

 

では具体的なコードの内容に入っていきましょう。

 

2.テトリミノが移動できるか判定するコード

まずは移動(左・右)に関するコードです。

下移動の時と同様に、無色かどうかをチェックするセル範囲について考えてみましょう。

以下、左移動に関してのイメージです。

こんな感じで、すべてのテトリミノについて、無色かどうか判定すべき範囲をリストアップしていきます。

また、テトリミノの種類だけでなく、回転によっても無色かどうか判定すべき範囲が変わってきますから、

すべての回転後の図形の種類についてもリストアップが必要です。

 

まとめると、以下の全図形について無色かどうか判定すべきセル範囲をリストアップするということです。

 

たくさんありますね。作業は単純なので頑張りましょう。

根気があればできます。

 

実際に作成したコードの一部をご紹介します。

 

Function checkleft(block As Integer, r As Integer, c As Integer, rotate_num As Integer) As Boolean
    Select Case rotate_num
        Case 0
            Select Case block
                Case 1, 7
                    If Range(Cells(r, c - 1), Cells(r + 1, c - 1)).Interior.ColorIndex = -4142 Then
                        checkleft = True
                    End If

   ・・・以下、回転後の図形の種類(rotate_num)、

      およびテトリミノの種類(block)ごとに上記と同様の記述を行う

 

 

これで、左に移動できる(左側が無色である=ブロックや壁がない)時に"True"を返す関数が完成しました。

これを左移動のコードに組み込めばOKです。

具体的には以下の通りです。

 

    If checkleft(block, r, c, rotate_num) = True Then
        If GetAsyncKeyState(vbKeyLeft) <> 0 Then
            c = c - 1
        End If
    End If

 

太字部分が今回新たに追加した内容、細字部分が前回紹介した内容になります。

これでブロックや壁がない箇所にのみ左移動ができるようになりました。

 

右移動に関しても左移動と同様に、

・無色であるか判定すべきセル範囲をリストアップ

・その範囲が無色である場合にTrueを返す関数を作成

・右移動の条件として当該関数=Trueであることを追加

すれば、移動範囲に制限をかけることができます。

 

以上で移動可能かの判定に関するコードの紹介を終わります。

 

3.テトリミノが回転できるかを判定するコード

続いて回転できるかを判定するコードです。

考え方は移動可能かの判定と同様です。

ポイントになるのは、「どの範囲を判定対象とすべきか」ということです。

 

移動の場合は表示する位置が変わるのみで、表示する図形自体は変わりませんでした。

ですので、どこを判定対象とすべきかわかりやすかったかと思います。

 

回転の場合は表示する位置に変更はありませんが、表示する図形に変更があります。

ですので、回転後の図形を踏まえて判定対象とすべき範囲を考える必要があります。

 

具体的なイメージは以下の通りです。

 

回転前の図形が赤点線部分、回転後の図形が黒色部分になります。

そして、無色と判定すべき範囲が赤色の枠で囲っている部分になります。

 

回転前の図形と回転後の図形で表示位置が一行ずれているのは、

回転するとともに自然落下(下移動)も行われますので、

それを加味しているためです。

 

イメージ図を見てわかるように、

回転前の図形から回転後の図形にするためには、

回転前の図形からみて、

回転後にブロックが来るであろう位置が無色である必要があります。

ということで、上の例では赤枠部分になるわけです。

 

こちらも移動可否の判定の時と同じように、

すべてのテトリミノの種類、すべての回転時の図形の種類ごとに、

無色と判定すべき範囲をリストアップが必要です。

 

また、上で説明した通り、回転前の図形から回転後の図形になるのを踏まえて、

無色と判定すべき範囲を考えなければなりません。

 

・・・かなり面倒ですね。より根気のいる作業です。

ただ、根気があればそんなに深い知識がなくてもできますので、

初心者にやさしい(?)コードだと思います。

 

具体的なコードの内容は、

移動可否の判定のものとほぼ同じ(無色と判定すべき範囲が違うのみ)ですので、

割愛します。

 

以上で回転可否の判定に関するコードの解説を終わります。

 

4.おわりに

今回はテトリミノを移動・回転させるにあたり、

移動・回転が可能な範囲を制限するのに必要なコードについて解説しました。

 

根気のいる作業と言った通り、コード化するとかなりの量のコードになります。

工夫すればもっとシンプルなコードになるのかもしれませんが、

初心者が作ったコードですのでご容赦ください。

 

ただ、実際にマクロを実行したときにはちゃんと動作します。

結果よければ見た目悪くてもよし、ということで。笑

 

ここまでの内容でかなりテトリスっぽくなってきましたね。

次回からはブロックが揃ったときの挙動を再現するために必要なコードを解説していきます。

 

ではまた。