コラム / テトリスぽいもの / 30



さて、段が消える処理の実装を考えます。
段が消えるかどうか調べるのは、
ピースを積んだときです。
もし、全部埋まっている段があれば、
その段を削除する処理を実行します。
段の削除は簡単です。
その段のフラグを全部バキバキにすればすみます。
問題はその後で、
上に乗っていたブロックがあればそれをずらさなければなりません。
ブロックの塊を下に落とす方法ですが、
ブロックを段の集まり と 考えれば簡単です。
まず、消された段が3段目だったとします。
そうしたら、4段目のデータを3段目にコピーします。
そのあと、4段目を消します。
4段目を消したら、5段目のデータを4段目にコピーします。
その後、5段目を消します。
そうしたら、5段目のデータを・・・
・・・
というように、下から順番に落としていけばいいのです。
しかし、そう考えると、
「消す」処理は要らないことに気付きます。
消しても消さなくても、どちらにしろ上の段に上書きされるからです。
そこで、あとで消す処理を完成させたとき、
ソースが読みやすくなるように、
「与えられた段のデータを、一段上のデータに書き換える」
という手続きを作ります。
落下処理はフィールドクラスに扱わせましょう。
TMapBlocksを編集します。
   TMapBlocks = Class(TObject)
   private
   public
       (略)
       procedure RewriteLineByOverLine(at:integer);
       procedure Draw;
   end;
なんだか怪しい英語です・・・
引数として与えられた段を、上の段のデータで上書きします。
実装部です。
procedure TMapBlocks.RewriteLineByOverLine(at:integer);
var i:integer;
begin
   For i:=0 to 9 do begin
       if at=0 then begin
           Blocks[at,i]:=False;
       end else begin
           Blocks[at,i]:=Blocks[at-1,i];
       end;
   end;
end;
外側のforループは、
段の10個のブロックを操作するための、横方向用ループです。
内側ではif elseを使っています。
もし、atが0、つまり、一番上の段で削除が発生した時は、
その上にはデータがないので(あったときはゲームオーバー
強制で偽を入れます。
atが0でないなら、その上の行をコピーします。
さて、
「与えられた段のデータを、その一つ上の段のデータで書き換える」
処理ができたら、
その処理を、
ブロックが揃った列から、
一番上まで順番に呼び出せば、
下から一段ずつ落ちて行って、
結局消された段の上のブロックが落ちたことになります。
では、次回で、
その消える行を指定して、
その行から一番上の行まで、順番に今の処理を呼び出す処理を作ります。