C++でつくったテトリスの完成品

前回宣言したとおり、今回はホールドの機能を実装します。

ホールドの機能を実装する

テトリスのガイドラインではホールドに関する記述があります。これによると

テトリミノを1個保持できる。
使うと現在のミノがホールドに入り、ホールドにあったミノが降ってくる
ホールドされているミノは存在しない場合は現在のミノがホールドに入りネクストにあるミノが降る。
1回使うと設置するまで使えない。

それからホールドするためのキーは「C」を使います。左回転ならZ、右回転ならX、ホールドはさらに右側にあるCです。

ではさっそくホールドの機能を実装していきましょう。そのために必要なメンバ変数とメンバ関数を追加します。

Tetris.h

ホールドされているテトリミノはフィールドの左側に表示させます。

そこでTetris::Draw関数にホールドされているテトリミノを描画するためのShowHold関数を追加します。

Tetris.cpp

TetriminoTypes列挙体へのNoneの追加

ホールドの処理をするとき、すでにホールドされているものがあれば入れ替えが必要です。

現在ホールドされているものを TetriminoTypes m_holdTetrimino;で表現したいのでTetriminoTypes列挙体にNoneを追加します。

Block.h

それからゲーム開始時にはホールドされているテトリミノは存在しないのでm_holdTetriminoにはTetriminoTypes::Noneを格納しておきます。

Tetris.cpp

ホールドされているテトリミノを表示するShowHold関数

あとはホールドされているものがあればフィールドの左側に描画します。テトリミノを描画する方法NEXTブロックの描画と同じ(違うのは描画する位置)なのでDrawNextBlock関数を使っています。

Tetris.cpp

ホールドを実行するHold関数

ホールドボタンが押されたらHold関数を実行します。ホールドのルールは「1回使うと設置するまで使えない」です。そこで一度ホールドしたら設置するまではクリアされないフラグをつくります。

再びホールドを可能にするには

ホールドするとテトリミノが設置されるまでホールドはできませんが、設置されてしまえなふたたびホールド可能になります。

これはテトリミノが設置されたタイミングでm_CanHoldをTRUEに変更すればいいですね。つまりFixBlocks関数が実行されたときです。

以上でホールドの機能を実装することができました。

細かい部分の修正

思ったよりも簡単に終わってしまったので、ちょっと細かい部分の修正をおこないます。

ゲームオーバー判定

ゲームオーバーになったらゲームオーバーになったことを示す文字列の表示とゲームにもう一度挑戦できる手段を用意しておかないといけません。

そこでヘッダーに以下を追加します。

Tetris.h

まずゲームオーバーの判定ですが、落下中のテトロミノが着地・固定されたあと新しいテトロミノが上から降ってきますが、このときすでに固定されているブロックと接触しているのであれば、ゲームオーバー状態になっていることがわかります。その場合は

キー操作をうけつけない
タイマーによるメッセージに対応しない

とよいと思われます。

新しいテトロミノが上方に出現するのはNewTetrimino関数が実行されたときです。ここでCanMove(0, 0)を実行すればテトロミノが動かない状態ですでに固定されているブロックと衝突しているかがわかります。

ゲームオーバーであることを示すメンバ関数m_IsGameOverを定義し、ゲームオーバーになったらこれをTRUEにします。

Tetris.cpp

それからゲームオーバーになってしまったら新しいテトロミノをつくるのをやめます。

またm_IsGameOverフラグの状態を取得するメンバ関数もつくります。これでTetrisクラスの外からもゲームオーバーであるかどうかがわかります。

ゲームに再挑戦できるようにする

キー操作が行なわれたときの処理です。ゲームオーバーのときにSキーを押すとゲームに再挑戦できます。ゲームオーバーのときはそれ以外のキー操作ができません。

MainWindow.cpp

タイマーに関するメッセージを処理する場合も同様にゲームオーバー時にはなにもしません。

MainWindow.cpp

ゲームを再開するときはTetris::Retry関数を実行します。スコアとホールド可能不可能のフラグ、ゲームオーバーフラグのクリア、次に落ちてくるテトリミノの情報の初期化をおこないます。それ以外の処理はInit関数でやってくれます。

Tetris.cpp

ゲームオーバー時にゲームオーバー表示をする

普通のゲームはゲームオーバーになったらゲームオーバーと表示されます。Tetris::Draw関数のなかでm_IsGameOverフラグがセットされているならゲームオーバー表示を実行する関数を呼び出すだけです。さっそくやってみましょう。PRESS S KEYと表示させることで、ゲームをもう一度するのであればSキーを押せばよいということもわかります。

Tetris.cpp