ワンポイントテクニック No.016 G800シリーズ対応

8方向移動判定の高速化


 ゲームなどでキャラを移動させる場合、論理式を使えば[8][2][4][6]で上下左右4方向に移動させるのは簡単にできるのですが8方向移動を行う場合は論理式を使ってもこれだけ長くなります。

10 CLS :X=99:Y=20
20 K=VAL INKEY$
30 V=(K=1)+(K=4)+(K=7)-(K=3)-(K=6)-(K=9)
40 W=(K=7)+(K=8)+(K=9)-(K=1)-(K=2)-(K=3)
50 GCURSOR (X,Y):GPRINT "0000000000000000"
60 X=X+V:Y=Y+W
70 GCURSOR (X,Y):GPRINT "D87C363C3C367CD8"
80 GOTO 20

 これでも、IF文を使えば8個になるわけだからかなり簡略化はされていますが、まだ工夫の余地はありそうです。テンキーを実際に見てもらえれば分かりますが、規則的な配列(特定キーの右は必ず1大きくなるし、上は必ず3大きくなる)なのでそれを数式で表すことで簡略化ができます。

10 CLS :X=99:Y=20
20 K=VAL INKEY$
30 W=INT ((6-K)/3):V=K+W*3-5:IF K=0THEN V=0:W=0
40 GCURSOR (X,Y):GPRINT "0000000000000000"
50 X=X+V:Y=Y+W
60 GCURSOR (X,Y):GPRINT "D87C363C3C367CD8"
70 GOTO 20

 [5]を基準にテンキーの見た目通りの移動をしているのですが、押してない場合は[0]を押していると判断されるためにそれを30行のIF文でそれを除外しています。
 なお、30行はIF文の代わりにSGNを用いてW=INT ((6-K)/3)*SGN K:V=(K+W*3-5)*SGN Kとすることもできます。どちらも同一動作ですがIF文の方が少し速く、SGNを使った方が少しメモリを節約できます。

 8方向移動は普通に処理をすれば判定が大変ですが、テンキーを使用時に限りこの方法によって簡単かつ高速に実現できるのでぜひ活用してみてください。


コラム パターン化されたIF文の簡略化

 この8方向移動判定のようにIF文に一定のパターンがある場合は多数のIF文があってもそれを1つか2つの式だけで置き換えることも可能です。私が作った「あとだしじゃんけん」のプログラムも何の工夫も無しに勝敗判定を行えば自分の手が3通り、相手の手が3通りで合計9通りのパターンが考えられIF文は9個必要になります。

Aが相手、Bが自分でグー=1、チョキ=2、パー=3
Dが勝敗判定で引き分け=0、勝ち=1、負け=2


とした場合、自分の手と相手の手が同じ場合(A=B)引き分けというのはすぐ分かり、相手が自分より1つ大きければ(A-B=1)勝ち2つ大きければ(A-B=2)負けというのも分かると思います。自分がチョキやパーの時は2つ大きなものというのが存在しないのでその場合は3を足すことで仮想的に比較が可能になります。(3を足せば相手の手がグー=4、チョキ=5となるため)
 これらをすべてまとめればD=A-B-(A<B)*3という1つの式のみで判定を行える理由が分かるでしょう。(3を足すと自分と相手の差が3以上になる場合が起こりうるために自分が相手より小さい場合のみ3を足している)
 別の観点から見ればA-Bを3で割った余りつまりD=(A-B) MOD 3で勝敗判定ができます。こちらの方が単純で分かりやすいのですが、剰余を返す演算子を持ってないポケコンBASICの場合は上記の方法の方が簡略化できます。

 このように一定のパターンがあるIF文の場合、法則性を数式化することによるIF文の大幅削減が可能な場合があります。だから、IF文が羅列するような場合は法則性がないか考えると良いです。


RETURN

inserted by FC2 system