前回告知したバグですが、
実は、途中まで作ってるときは、
自分で気付いておらず、
記事を書きながら実行したら例外発生イヤーンと
なったわけでして、
そのバグって言うのは、
「ブロックの初期位置が0未満だと落ちてこない&例外が出る」
ってものです。
これができないと、画面のてっぺんからピースが出てくる動きが
表現できませんよね。
えー、原因ですが、
TMapBlocks.isBlock 関数の挙動が悪かったようです。
再掲してみます。
function TMapBlocks.isBlock(x,y:integer):Boolean;
begin
if (x<0)or(9<x)or(y<0)or(19<y) then begin
Result:=True;//フィールドの外は埋まっている
Exit;//終了
end;
//範囲内に収まっていたら
Result:=Blocks[y,x];//そのまま返す
end;
えー、画面のてっぺん、つまり、y<0の条件ですが、
これのせいで、「画面のてっぺんはブロックで埋まっている」
という概念になっています。
で、ピースのメインルーチンでは、
isHitという関数を使って、
「もし下に一歩下りたときブロックに重なってしまうか」
という判定をしていました。
もし、ピースの初期位置が0<yなら、
一歩降りても、自分の長さが2以上なので、
一歩降りる→埋まる
となり、ピースは、埋まったときの自殺処理、すなわち、
「フィールドに自分をコピーして自殺」
をしようとします。
さて、ここで例外が発生します。
「自分をコピーする処理の内部では、範囲判定をしていませんでした。」
すると、
「画面の外、つまり、y座標が負の数の座標にフラグを立てようとする」
となります。
配列の要素を参照するとき、
定義していない番号を参照しようとすると、
「アドレス○○でアドレス○○に対する書き込み違反」
って感じのエラーが出ます。
という、バグなのでした。
直すのは簡単です。
isBlockの概念を
こうするだけです。
function TMapBlocks.isBlock(x,y:integer):Boolean;
begin
if (x<0)or(9<x)or(y<0)or(19<y) then begin
Result:=True;//フィールドの外は埋まっている
Exit;//終了
end;
//範囲内に収まっていたら
Result:=Blocks[y,x];//そのまま返す
end;
↓変更↓
function TMapBlocks.isBlock(x,y:integer):Boolean;
begin
if (x<0)or(9<x)or(19<y) then begin
Result:=True;//フィールドの外は埋まっている
Exit;//終了
end;
//範囲内に収まっていたら
Result:=Blocks[y,x];//そのまま返す
end;
if条件の(y<0)を取るだけです。(繋いでるorも一個取ってね
それじゃぁ、初期化文を直しましょう。
FormのonCreateです。
procedure TForm1.FormCreate(Sender: TObject);
begin
(略)
Piece.y:=0;
(略)
end;
↓
procedure TForm1.FormCreate(Sender: TObject);
begin
(略)
Piece.y:=-3;
(略)
end;
これで実行してみてください。
アッー! まだバグってた!!!!
デバッグによるバグはよくあります・・・・
isBlockの直し方を間違えてました。
function TMapBlocks.isBlock(x,y:integer):Boolean;
begin
if (x<0)or(9<x)or(19<y) then begin
Result:=True;//フィールドの外は埋まっている
Exit;//終了
end;
//範囲内に収まっていたら
Result:=Blocks[y,x];//そのまま返す
end;
ifはスルーしますが、
Result:=Blocks[y,x];//そのまま返す
で、範囲外参照になっちゃいますwwww
さらに編集
function TMapBlocks.isBlock(x,y:integer):Boolean;
begin
if (x<0)or(9<x)or(19<y) then begin
Result:=True;//フィールドの 左 右 下 はうまっている
Exit;//終了
end;
if y<0 then begin
Result:=False;//フィールドの 上 なら、埋まっていない
Exit;
end;
//フィールドの 内側 なら
Result:=Blocks[y,x];//そのまま返す
end;
if y<0 then begin
Result:=False;//フィールドの 上 なら、埋まっていない
Exit;
end;
を追加しました。
yが0未満、つまり、フィールドより上の範囲をみたら、
強制でフラグオフ(偽(False))にして、Exitします。
なんかもうゴリゴリです。ウホウホ。
今度こそ実行してOKです。
落ちてきた落ちてきた。
コンテンツ
最新の12件
2023-06-12
2021-02-15
2013-06-19
2012-07-14
2012-02-04
2012-01-06
2011-03-31
2010-08-26
2010-03-15
2009-10-21
2009-02-12
2008-11-18
メニュー編集
- counter: 898
- today: 1
- yesterday: 0
- online: 1