HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2022
0411
アキアキノヒロロ[if and] [if or] [if &] [if |] 条件に、[stick key] の [key&_] を使う方法6解決


アキアキノヒロロ

リンク

2022/4/11(Mon) 06:44:43|NO.95959

題名の通りです。

AおよびBは、キーの値として
> [if key&A & key&B]([if key&A | key&B])
> [if key&A and key&B]([if key&A or key&B])
は、記述が通らないようです。

> [if key=A & key=B]([if key=A | key=B])
> [if key=A and key=B]([if key=A or key=B])
とするしかないのでしょうか。

もし、[key=] とした場合、当初 [key&] で望んだ結果と同じ結果になるのでしょうか。
どうも、試しようも分からないのですが、どうなんでしょう。



この記事に返信する


沢渡

リンク

2022/4/11(Mon) 08:55:23|NO.95960

AとBを足したものをCとして、
「AとBのどちらかが押されている」の判定なら

if key&C
とすれば良いですし、
「AとBの両方が押されている(他のキーを押しているかどうかは不問)」の
判定なら、

if (key&C)=C
とすれば良いのではないでしょうか。



アキアキノヒロロ

リンク

2022/4/11(Mon) 10:15:23|NO.95961

沢渡 さん、有難うございます。

そう考えればいい訳なんですね。
どうも、[&] は苦手です。
[stick key] の [key&_] は、あまり考えずに習慣的に使っていて、
こいう場合、はたと立ち止まってしまいます。

分かりやすく教えて頂けて、うれしいです。
何年も使っていながら、ちっとも理解できていなくて、
基本的なことの大事さを痛感します。



MIZUSHIKI

リンク

2022/4/11(Mon) 19:10:14|NO.95966

解決されていますが、少しだけ考え方の補足をしてみたいと思います。


ifの(実際の)仕様 と「&」の考え方 を勘違いしているとハマりやすい罠の1つだと思います。
まず、if自体は「0以外の数字のとき」に条件を満たすという判定をします。逆に「0の場合」のみ条件を満たさない(else)ということになります。

「え、条件式を書くんでしょ? >=(以上) や <(未満) みたいな記号も使えてるけど?」と思われるかもしれません。

ifで使われている『条件式』はそれ単体で機能し、条件を満たしているときに「1」となり、満たしていなければ「0」となります。
mes (11 > 2) や mes (11 < 2) 等をやってみると分かりますが、条件式自体は計算式であるかのように振る舞います。

そして「&」の考え方ですが、、、
言葉で伝えるのが難しい(ニガテ)なので、下のスクリプトを実行してみてください。

#define mes0b_8bit(%1) gcx=ginfo_cx : p1=%1 : mes strf("%%3d -> 0b",p1),1 : repeat 8 : mes p1>>(7-cnt)&1,1 : loop : p1="%1" : p1=strtrim(p1) : if p1!str(%1)&p1!="cnt"{mes " ( = "+p1+" )",1} : mes "" : pos gcx mes "それぞれの数値や条件式の結果を2進数で表示しています。" mes "" key = 11 A = 9 B = 2 mes0b_8bit key mes0b_8bit A mes0b_8bit key&A if key&A : color 255 : mes "if OK(0以外!)" : else : color ,,255 : mes "if NG(0だよ!)" color : mes "" mes0b_8bit key mes0b_8bit B mes0b_8bit key&B if key&B : color 255 : mes "if OK(0以外!)" : else : color ,,255 : mes "if NG(0だよ!)" color : mes "" mes0b_8bit key&A mes0b_8bit key&B mes0b_8bit (key&A) & (key&B) ;優先順位に注意! →もし「 key&A | key&B 」の場合どの記号も優先順位が同じなので手前から順に処理され →「 ( (key&A) | key ) & B 」となってしまいます。括弧を使いましょう。 if (key&A) & (key&B) : color 255 : mes "if OK(0以外!)" : else : color ,,255 : mes "if NG(0だよ!)" color : mes "" : mes "" mes "【 解決策の案 】" mes0b_8bit (key&A)!0 mes0b_8bit (key&B)!0 mes0b_8bit (key&A)!0 & (key&B)!0 if (key&A)!0 & (key&B)!0 : color 255 : mes "if OK(0以外!)" : else : color ,,255 : mes "if NG(0だよ!)"
「&(and)」や「|(or)」等は『論理演算』と言います。

「key & A」は、key と A という2つの数値を 2進数 で表したときにそれぞれ同じ桁のビットを見て両方 1 だった場合、出力するとき(key & A)も 1 にします。それを全ての桁で行っています。
(詳しくはネットで検索すると正しくもっとわかりやすい情報がたくさんあると思います。気になったら「|(or)」も調べてみてください。)

今回アキアキノヒロロさんの言っていたのは、3つ目の例に当てはまります。
key&A も key&B も「0以外」にはなるけれど、それぞれ 1 になっているビットの位置がかみ合っていないので、(key&A) & (key&B) してしまうと「0」になってしまうわけです。

解決策としては、上記のように (key&A)!0 で先に「0 か 1」にしてしまう方法が考えられます。

;ただし、そのままでもタマタマ上手くいってしまうこともあります。
;例えば、B = 3 に変更してみて下さい。3つ目の例も OK になることがわかります。


「え、待って! なんでそもそもそんな2進数に置き換えて考えないといけないようなものを使ってるの!? stick命令の説明でも書いてあるし!」
と思ったかもしれませんが、これはこれで『複数のスイッチON/OFF』判定にとても便利なのです。
例えば、stick命令に使われているキーを2進数で表示してみましょう。

#define mes0b_8bit(%1) gcx=ginfo_cx : p1=%1 : mes strf("%%3d -> 0b",p1),1 : repeat 8 : mes p1>>(7-cnt)&1,1 : loop : p1="%1" : p1=strtrim(p1) : if p1!str(%1)&p1!="cnt"{mes " ( = "+p1+" )",1} : mes "" : pos gcx mes "stickで使われるキー" カーソルキー左 = 1 カーソルキー上 = 2 カーソルキー右 = 4 カーソルキー下 = 8 スペースキー = 16 Enterキー = 32 Ctrlキー = 64 ESCキー = 128 mes0b_8bit カーソルキー左 mes0b_8bit カーソルキー上 mes0b_8bit カーソルキー右 mes0b_8bit カーソルキー下 mes0b_8bit スペースキー mes0b_8bit Enterキー mes0b_8bit Ctrlキー mes0b_8bit ESCキー mes "" mes "stickの変数を2進数表示!(カーソルの左と上の2つとかを押してみよう!)" gcy = ginfo_cy repeat redraw 0 color 255,255,255 : boxf ,gcy : color : pos 0,gcy stick _stick_, -1 ;全部を非トリガータイプキー指定 mes0b_8bit _stick_ /* if _stick_ & 1 : mes "左!" if _stick_ & 2 : mes "上!" if _stick_ & 4 : mes "右!" if _stick_ & 8 : mes "下!" */ redraw 1 await 16 loop
それぞれ1つの桁だけに「1」が出てきますよね。
この1つ1つの桁が『スイッチのON/OFF』の判定に利用できる!ということになります。
数値の範囲は -2147483648 〜 2147483647 で、32ビットです。(HSPの整数型[int])
「1つの数値で32個のスイッチON/OFFを同時に表現できる」という風に考えることができます。



窓月らら

リンク

2022/4/15(Fri) 12:15:36|NO.95996

つまり2進数を知れば理解できます。こういうことです。
よく命令の説明に 1,2,4,8,16,32,64,128... と指定するものがありますが、
あれはビット列(2進数)を10進数で表すとそうなるって話。

a(0)=%00000001 // 1 a(1)=%00000010 // 2 a(2)=%00000100 // 4 a(3)=%00001000 // 8 a(4)=%00010000 // 16 a(5)=%00100000 // 32 a(6)=%01000000 // 64 a(7)=%10000000 // 128 repeat 8: mes a(cnt): loop



アキアキノヒロロ

リンク

2022/4/15(Fri) 14:50:12|NO.96000

MIZUSHIKI さん、窓月らら さん、
気づかずそのままにしていたこと、すいませんでした。

基礎知識として、身につけておかないといけないことなんですね。
ただ、それを感覚的にも納得できるという実感がなかなか持てません。

「2進数、10進数」「条件式自体は計算式であるかのよう」「「&」の考え方」
これらが、ごっちゃになっています。
条件式を書いたり、条件式に出会ったりするたびに、
このことをそうとう意識する癖をつけないと、
感覚的にも自分のものにすることは出来そうにありません。
難しいですが、そうしていきます。

有難うございました。



MIZUSHIKI

リンク

2022/4/15(Fri) 19:08:55|NO.96009

すみません。ちょっと私も怒涛の勢いで色々と書き過ぎました(^^;;

アキアキノヒロロさんの望んでいる
>AおよびBは、キーの値として
> [if key&A & key&B]([if key&A | key&B])

この記述に近い書き方として

if (key&A)!0 & (key&B)!0 : if (key&A)!0 | (key&B)!0 :
というような書き方が(私的には)オススメですよ。っていうお話でした。(詳細抜きに要約すると。)

今は「へーそうなんだ(そう書けるんだ)」で真似て書いてみて、色々作っていって時間がたつ中で「こういうことか」と自分の中で腑に落ちるところまで行けば良いと思います。
みんなそういうものだと思います。私も含めて。



ONION software Copyright 1997-2023(c) All rights reserved.