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

SGNで場合分けをする


 SGNは数値を符号化するものですがこれを上手く利用すればIF文や論理式の代用もできます。
 たとえばB=SGN (A-9)はIF文で表すと下記のようになります。

IF A>9 THEN B=1
IF A=9 THEN B=0
IF A<9 THEN B=-1

 作ろうとしているプログラム内でA>9とならないことが分かっているならばB=(A<9)B=SGN (A-9)と置き換え可能になります。IF (条件式) THEN A=-1 ELSE A=0A=(条件式)という論理式で置き換えることができるのですが、論理式を使わずにSGNを使うことも可能ということです。

 たとえばキャラを動作させる場合、画面からはみ出ないように止める必要があります。X座標の範囲が0≦X≦39となっている場合はSGNを使えば論理式を下記のように変更すればよいです。

 左方向右方向
論理式を使用X=X+(X>0)X=X-(X<39)
SGNを使用X=X-SGN XX=X+SGN (X-39)

 見ての通り論理式とほぼ一緒(符号が逆になっている程度)ですね。論理式が使えないPB-100などでは論理式の代わりにこのSGNを使う機会が多いためポピュラーなテクニックとなっていますが、論理式に対応しているポケコンの場合論理式を使う方がポピュラーなのであまり馴染みのないという人もいるかもしれませんので別の例も書いておきます。

 変数Aの値を0,1,2,3,4,0,1,2,3,4,0…のようにループさせる場合を考えてみます。それを論理式とSGNを使えば下記のようにすればできます。

論理式を使用A=A+1+(A=4)*5
SGNを使用A=A-4+SGN (4-A)*5

 符号が逆になっている関係上「+1」と「-4」という違いがあるものの基本的には同じであることが分かると思います。そうなると「結局、論理式で表現できるならSGNを使う必要なんてないのでは・・・?」と考える人も多いのではないでしょうか。実際、(X>0)をSGN Xに置き換える以外は速度的には論理式の方が速い上に大半はSGNに変更してもメモリ節約にはならないのです。
 しかし、冒頭のIF文への置き換えのようにSGNは1つの式で3通りの場合分けができるというメリットもあります。論理式だと1つではそれより大きいか小さいか(もしくは等しいか等しくないか)2通りの場合分けしかできないため3つの区間における場合分けをする場合には2つの式を使用する必要があります。
 下記のPRINT文はVS50m走の勝敗判定の部分ですが、Xが1プレイヤーの座標、Yが2プレイヤーの座標でゴールしたときの座標の大きな方が勝利となるように画面表示を行っています。

PRINT MID$ ("1P WIN=DRAW=2P WIN",SGN (Y-X)*6+7,6)

これをSGNを使わずに論理式を使えば次のようになります。

PRINT MID$ ("1P WIN=DRAW=2P WIN",((Y<=X)+(X=Y))*6+13,6)

 SGNの方がすっきりして分かりやすいと思います。このように間に等号を含む3通りの場合分けを行う場合は論理式よりも簡単に表現ができるのです。
 では、等号を含まない場合は使えないのかというとそんなことはありません。工夫次第では使用可能なのです。
 例えば、X座標が(X<0、0≦X<240、X≧240)という3つの状態を考える場合それを判断するには論理式やSGNを使えば下記のようにすればよいです。

論理式を使用A=(X>=0)+(X>=240)X<0ならA=0、0≦X<240ならA=-1、X≧240ならA=-2
SGNを使用A=SGN INT (X/240)X<0ならA=-1、0≦X<240ならA=0、X≧240ならA=1

 SGNの方は1つの式でちゃんと3通りに場合分けが出来ていることが分かると思います。
 ただ、論理式のところでも書いたように無理に置き換えをすればかえって遅くなってしまいかねないです。論理式とSGNのどっちが良いかはケースバイケースなので状況に応じて使い分けができるのが望ましいと思います。


RETURN

inserted by FC2 system