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


HSPTV!掲示板


未解決 解決 停止 削除要請

2008
0311
GOTOU複数の反応の判定を行うには?31解決


GOTOU

リンク

2008/3/11(Tue) 23:36:57|NO.14106

画面に左右2つの円を表示し、「左」「右」の順でクリックすると、
得点が入るようなスクリプトを書きたいのですが、
クリックがどの順番で行われたか1回ずつ記録&判定するにはどうしたら良いでしょうか。
クリックがあった場合の、「左」「右」の座標判定までは出来たのですが、
以下の部分で躓いてしまいました。

・クリックされた位置の順序(「左」か「右」か「それ以外」か)
・外部ファイルへのsave方法

判りづらい質問で申し訳ございませんが、宜しくお願い致します。



この記事に返信する


As

リンク

2008/3/12(Wed) 01:32:46|NO.14115


#define BTN_LEFT 1 #define BTN_RIGHT 2 #module #define rad double(3.14159265)/double(180) #defcfunc redrect int _x,int _y,int size, int show_debug if show_debug = 1 { repeat 360 pset size+ginfo(22)+double(size)*sin(double(rad*cnt)),size+ginfo(23)+double(size)*cos(double(rad*cnt)) loop } px = size+ginfo(22) py = size+ginfo(23) if show_debug =1 { pset px , py pset _x, _y } if size>( sqrt(abs((px-_x)*(px-_x)+(py-_y)*(py-_y) ))) : return 1 return 0 #global onclick gosub *cli onexit gosub *exi data="" objsize 100,70 pos 10,320: listbox list,70,data idlist=stat color 0,0,0 circle 50,100,250,300 color 240,240,240 circle 400,100,600,300 stop *cli pos 50,100 if (flag!BTN_LEFT)&(redrect(mousex,mousey,100,0)){ flag=BTN_LEFT }else{ pos 400,100 if (flag!BTN_RIGHT)&(redrect(mousex,mousey,100,0)){ flag=BTN_RIGHT }else{ notesel data : count+ : noteadd ""+count+"回目 それ以外",0 : objprm idlist,data return } } if flag = BTN_RIGHT{ color 0,0,0 notesel data : count+ : noteadd ""+count+"回目 右",0 : objprm idlist,data }else{ color 240,240,240 } circle 50,100,250,300 if flag = BTN_LEFT{ color 0,0,0 notesel data : count+ : noteadd ""+count+"回目 左",0 : objprm idlist,data }else{ color 240,240,240 } circle 400,100,600,300 return *exi //notesel data //notesave dir_cur+"data.ini" end



GOTOU

リンク

2008/3/21(Fri) 18:43:26|NO.14473

有難うございます。
試行錯誤の結果、目的に合わせて下記の様に書き換えてみました。
ただ、円の左上の当たりでクリックすると、反応が検出されません・・・
設定がずれているのだとは思いますが、どうしたら良いでしょうか。
また、「左右左」と順番に押した場合にメッセージが出るようにするには、

#define BTN_LEFT 1 #define BTN_RIGHT 2
の定義を変更または、新しい定義を追加すれば良いでしょうか。
初心者の質問で申し訳ございませんが、宜しくお願い致します。


scrExp = 0 screen scrExp, ginfo_dispx, ginfo_dispy, 4, 0, 0;窓枠付き #define BTN_LEFT 1 #define BTN_RIGHT 2 #module #define rad double(3.14159265)/double(180) #defcfunc redrect int _x,int _y,int size, int show_debug if show_debug = 1 { repeat 360 pset size+ginfo(22)+double(size)*sin(double(rad*cnt)),size+ginfo(23)+double(size)*cos(double(rad*cnt)) loop } px = size+ginfo(22) py = size+ginfo(23) if show_debug =1 { pset px , py pset _x, _y } if size>( sqrt(abs((px-_x)*(px-_x)+(py-_y)*(py-_y) ))) : return 1 return 0 #global onclick gosub *cli onexit gosub *exi data="" objsize 100,70 pos 10,320: listbox list,70,data idlist=stat scrWidth = ginfo_dispx scrHeight = ginfo_dispy poscircleX = (scrWidth / 2 - 100) poscircleY = scrHeight * 6 / 10 color 255,150,150 circle poscircleX+350,poscircleY-200,poscircleX+450,poscircleY-100;right circle poscircleX-250,poscircleY-200,poscircleX-150,poscircleY-100;left stop *cli pos poscircleX-250,poscircleY-200 if redrect(mousex,mousey,100,0){ flag=BTN_LEFT }else{ pos poscircleX+350,poscircleY-200 if redrect(mousex,mousey,100,0){ flag=BTN_RIGHT }else{ notesel data : count+ : noteadd ""+count+"回目 それ以外",0 : objprm idlist,data return } } if flag = BTN_RIGHT{ notesel data : count+ : noteadd ""+count+"回目 右",0 : objprm idlist,data }else{ } circle poscircleX-250,poscircleY-200,poscircleX-150,poscircleY-100;right if flag = BTN_LEFT{ notesel data : count+ : noteadd ""+count+"回目 左",0 : objprm idlist,data }else{ } circle poscircleX+350,poscircleY-200,poscircleX+450,poscircleY-100;left return *exi //notesel data //notesave dir_cur+"data.ini" end



As

リンク

2008/3/21(Fri) 19:52:13|NO.14474

>また、「左右左」と順番に押した場合にメッセージが出るようにするに
記録リストの3行目まで、つまり3回分までの記録を条件式で識別すれば可能です。
noteget と if を使えば・・・で き ま す よ ね ?


>pos x,y
>redrect(mousex,mousey,100,1)
この関数は、100ドットの円の範囲内にマウスポインタがある場合は1を返すという
範囲条件関数です。これをif文に使用し、描画を分けていたこと わ か り ま し た よ ね・・・?


つまり、この円範囲の条件式と、円の描画はまったく別ものです。
ここの値を変更せずに、円の描画だけ変更したのでは、ずれてしまうのはあたりまえです。
コメント行で関数の説明は時間がなかったのでできませんでしたが、redrect関数の第4パラメータ
の”show_debug”には気づきましたか?
このフラグを1にすることで、if文の条件判定の際に範囲を描画するようになります。

一度、redrect関数の第4パラメータを1に設定上、動作を確かめてみてください。



GOTOU

リンク

2008/3/21(Fri) 23:33:59|NO.14488

有り難うございます。
redrect関数の第4パラメータの"show_debug"の使い方が判りました。
早速sizeを訂正して、ズレをなくすことが出来ました。

>>また、「左右左」と順番に押した場合にメッセージが出るように
>記録リストの3行目まで、つまり3回分までの記録を条件式で識別すれば可能です。
>noteget と if を使えば・・・で き ま す よ ね ?

おっしゃっている意味は理解出来るのですが、
notegetの使い方が理解出来ず、上手く行きません。
下記のスクリプトで実行すると、何故か2〜8回目の反応が履歴に入ってしまいます。


notesel data noteload dir_cur+"data.ini" noteget check0,0;1回目の反応を拾う noteget check1,1;2回目の反応を拾う if check0 = BTN_LEFT and check1 = BTN_RIGHT{;反応が右か左かをチェック pos 0,0 mes check0 mes check1 }



GOTOU

リンク

2008/3/23(Sun) 00:24:57|NO.14510

試行錯誤の上、何とか形になってきました。
ただ、1回目「左」かつ2回目「右」かつ3回目「左」を定義するif文が上手く行きません。


noteget check,0 if check = "1回目 左" { pos 0,0 mes check } noteget check1,0 if check = "2回目 右" { pos 100,0 mes check } noteget check,0 if check = "3回目 左" { pos 200,0 mes check }

各反応を検出してメッセージを出すのは出来るのですが、
例えば、「左右左」という複数反応をメッセージ表示の条件にするには、
どのようにしてif文を作れば良いのでしょうか。



ANTARES

リンク

2008/3/23(Sun) 07:05:21|NO.14517

>例えば、「左右左」という複数反応をメッセージ表示の条件にするには、
>どのようにしてif文を作れば良いのでしょうか。

 今一、仕様がよくわからないので、いい加減な仕様です。

<前略>

scrWidth = ginfo_dispx scrHeight = ginfo_dispy poscircleX = (scrWidth / 2 - 100) poscircleY = scrHeight * 6 / 10 num=3 dim seq,num seq=BTN_LEFT, BTN_RIGHT, BTN_LEFT sdim dir,10,3 dir="","左","右" notesel data size=100 xright=poscircleX+350 yright=poscircleY-200 xleft=poscircleX-250 yleft=poscircleY-200 color 255,150,150 circle xright,yright,xright+size,yright+size;right circle xleft,yleft,xleft+size,yleft+size;left stop *cli pos xleft,yleft flag=redrect(mousex,mousey,size/2,0) if flag==0 { pos xright,yright if redrect(mousex,mousey,size/2,0): flag=2 } if flag==seq(count) { count++ noteadd ""+count+"回目 "+dir(flag) objprm idlist,data } if count<num: return dialog "cleared!!" *exi //notesel data //notesave dir_cur+"data.ini" end



GOTOU

リンク

2008/3/24(Mon) 02:37:07|NO.14541

有り難うございます、勉強になります。
わかりにくいかも知れませんが、仕様としては、
1回目に「左」でメッセージ、2回目は「左右」でメッセージ、
3回目は「左右左」でメッセージを表示(実際にはカウンタの得点を上げます)、
というようにしたいのです。

seqに入れた配列の順序で反応があったらメッセージを表示し、
反応の数をfor文で1回ずつもしくはランダムに増やして系列を長く設定し、
かつ全ての反応を記録する仕様にするのが目的です。



GOTOU

リンク

2008/3/24(Mon) 19:50:57|NO.14553

note命令を使うと、実用場面で処理が遅くなるようなので、
instrを使って配列を読み出すように工夫してみました。


;(前略) if num=1{ seq=BTN_LEFT } if num=2{ seq=BTN_LEFT, BTN_RIGHT } if num=3{ seq=BTN_LEFT, BTN_RIGHT, BTN_LEFT } stop *cli num = 2;例えば、numが2の場合・・・ pos xleft,yleft;left if redrect(mousex,mousey,size/2,0){ flag==1 if flag ==1{ notesel data : count+ : noteadd ""+count+"回目" +dir(flag),0: objprm idlist,data }else{ } circle xleft,yleft,xleft+size,yleft+size;left }else{ pos xright,yright;right if redrect(mousex,mousey,size/2,0){ flag==2 if flag ==2{ notesel data : count+ : noteadd ""+count+"回目" +dir(flag),0: objprm idlist,data }else{ } circle xright,yright,xright+size,yright+size;right }else{ check_count+ if check_count=num { gosub *check } return *check check_seq =instr (data,i,"seq") if check_seq = -1 { dialog "notfound" else { dialog "cleard" } check_count = 0 return *exi //notesel data //notesave dir_cur+"data.ini" end
ただ、定義を間違えているようで、
seqの配列でも、そうでなくても"notfound"が表示されています。
if文が機能していないのでしょうか・・・

*check check_seq =instr (data,i,"seq") if check_seq = -1 { dialog "notfound" else { dialog "cleard" }



ANTARES

リンク

2008/3/24(Mon) 23:47:40|NO.14559

>1回目に「左」でメッセージ、2回目は「左右」でメッセージ、
>3回目は「左右左」でメッセージを表示(実際にはカウンタの得点を上げます)、
>というようにしたいのです。
以下のような意味と考えていいですか?
・1回目が左だったらメッセージ
・1回目が左で2回目が右だったらメッセージ
・1回目が左で2回目が右で3回目が左だったらメッセージ

それ以外の場合は終了ということでいいですか?

<前略>

if flag==seq(count) { count++ noteadd ""+count+"回目 "+dir(flag) objprm idlist,data } else { end }
<後略>



As

リンク

2008/3/25(Tue) 01:23:41|NO.14569


scrExp = 0 screen scrExp, ginfo_dispx, ginfo_dispy, 4, 0, 0;窓枠付き #define BTN_LEFT 1 #define BTN_RIGHT 2 #module #define rad double(3.14159265)/double(180) #defcfunc redrect int _x,int _y,int size, int show_debug if show_debug = 1 { repeat 360 pset size+ginfo(22)+double(size)*sin(double(rad*cnt)),size+ginfo(23)+double(size)*cos(double(rad*cnt)) loop } px = size+ginfo(22) py = size+ginfo(23) if show_debug =1 { pset px , py pset _x, _y } if size>( sqrt(abs((px-_x)*(px-_x)+(py-_y)*(py-_y) ))) : return 1 return 0 #global onclick gosub *cli onexit gosub *exi data="" objsize 100,70 pos 10,320: listbox list,70,data idlist=stat //円の位置を指定 scrWidth = ginfo_dispx scrHeight = ginfo_dispy poscircleX = (scrWidth / 2 - 100) poscircleY = scrHeight * 6 / 10 //予め描画 color 255,150,150 circle poscircleX+350,poscircleY-200,poscircleX+450,poscircleY-100;right circle poscircleX-250,poscircleY-200,poscircleX-150,poscircleY-100;left /* ↓ これはなに? この状態ではnumには0が代入されているので、どれも実行されていないと思うんだけど */ //1番目 if num=1{ seq=BTN_LEFT } //2番目 if num=2{ seq=BTN_LEFT, BTN_RIGHT } //3番目 if num=3{ seq=BTN_LEFT, BTN_RIGHT, BTN_LEFT } stop *cli num = 2;例えば、numが2の場合・・・ pos xleft,yleft;left //左のボタンの描画位置を指定 if redrect(mousex,mousey,size/2,0){ //左のボタンの上にマウスポインタがあるかどうか調べる flag==1 //変数flagに1を代入 if flag ==1{ //フラグに1が代入されていた場合実行 -> なぜ //わざわざ上文でflagに1を代入する必要がある?デバッグだとしてもおかしい notesel data : count+ : noteadd ""+count+"回目" +dir(flag),0: objprm idlist,data //↑noteselを左と右で定義しているがひとつで十分:ログに追加: オブジェクトの更新 }else{ } circle xleft,yleft,xleft+size,yleft+size;left //楕円描画 }else{ pos xright,yright //右のボタンの描画位置を指定 if redrect(mousex,mousey,size/2,0){ flag==2 //flag=2 恐らくBTN_RIGHT? 定数を使ったほうが分かりやすい if flag ==2{ notesel data : count+ : noteadd ""+count+"回目" +dir(flag),0: objprm idlist,data //ログ更新 }else{ } circle xright,yright,xright+size,yright+size;right //右円描画 }else{ } //閉じられていませんでした check_count+ if check_count=num { // gosub *check } return *check check_seq =instr (data,i,"seq") //恐らく、data内にseqという文字列があればクリアというカタチかとはおもいますが、、 if check_seq = -1 { dialog "notfound" }else { //else{ になってましたよ。 これでもいいのかもしれませんが、 dialog "cleard" } check_count = 0 return *exi //notesel data //notesave dir_cur+"data.ini" end







とりあえず、指摘したいところがかなりあるのですが、具体的な解説を行うのはこの質問の
タイトルで述べられていることと関係ないように思えるので、アドバイスにまとめさせて
いただきます。


 まず、文字列と変数の区別をつけるようにしてください。また処理が重くなるとinstrを
使われているようですが、instrもnote命令も同じようなものです。本当に処理を早く
したいのであれば、文字列ではなく数値だけで処理を考えるべきです。

また、このプログラムはリアルタイムな処理を要求するわけではないので、Note命令でも
十分にいけますし、そのほうが簡単です。\nを区切りとしてNoteadd命令はシフトしてくれます。
それを有効に使いました。だから、instrを使わずに普通に、notget命令で取得したほうが
楽ですし、高速だとは思います。またログにリストボックスを使いましたが、そのリストボックス
の結果を数値のみにすることでnote命令だけで可能になります。以下例は、ログに数値のみの
結果が代入されている場合を考えた左右左の条件式です。


sdim dir ,3 repeat 3 notesel dir(cnt) noteget 2-cnt loop if int(dir(0))=BTN_LEFT{ if int(dir(1))=BTN_RIGHT{ if int(dir(2))=BTN_LEFT{ mes "hit" } } }



GOTOU

リンク

2008/3/25(Tue) 13:23:39|NO.14576

ANTARES様
>・1回目が左だったらメッセージ
>・1回目が左で2回目が右だったらメッセージ
>・1回目が左で2回目が右で3回目が左だったらメッセージ
>それ以外の場合は終了ということでいいですか?

説明が至らず、申し訳ありません。
最終的には、
seq_numのような変数に、系列(左と右の組み合わせ)を代入して、
seq_num=1の時は、「左」の時のみメッセージ。
その他の反応は記録だけを行う。
メッセージを表示したら、メッセージ表示を記録し、
5回連続表示まで繰り返して、seq_numを増やす。
seq_num=2の時は、「左右」の時にのみメッセージ。
その他の反応は記録だけを行う。
これが5回連続表示まで繰り返して、seq_numの値を増やす。

以下、繰り返し。

seq_numの数は1〜6迄増加するように設定。
seq_num=6の時のみ、10回連続メッセージが表示されたら、
終了。

という仕様のものを作ります。

As様
丁寧な説明を頂き、有難うございます。
数値を使って処理した方が速いようですね、頑張ってみます。

所で、下記を加えて実行すると、☆の行で、
「変数名が指定されていません」というエラーになるのですが、
noteget dir(2-cnt)でしょうか・・・


sdim dir ,3 repeat 3 notesel dir(cnt) noteget 2-cnt;☆ loop



As

リンク

2008/3/25(Tue) 22:24:31|NO.14590

notegetを noteget data,2-cnt

にしてください



ANTARES

リンク

2008/3/26(Wed) 02:00:13|NO.14591

さっぱりわかりません。

>seq_numのような変数に、系列(左と右の組み合わせ)を代入して、
 「系列(左と右の組み合わせ)を代入」するということは、
seq_numは配列なのですか?
配列でないとしたら「系列」とは何?

>seq_num=1の時は、「左」の時のみメッセージ。
 系列を代入するのに数値が入っているとはどういうこと?
もしかして系列なんかじゃなくて、単なる試行番号?

>その他の反応は記録だけを行う。
 何を記録するのですか?

>メッセージを表示したら、メッセージ表示を記録し、
>5回連続表示まで繰り返して、seq_numを増やす。
 「5回連続でメッセージを表示するまで繰り返した後、seq_numを増やす」
という意味ですか?
 だとしたら、5という数値はどこから出てきた?
5回繰り返すまで増やさないseq_numって一体、何?
 2回目にメッセージが出なかったらどうするのですか?
記録のみ?
1回目にメッセージが出なかったらどちらをクリックしても
5回連続、記録のみ?

>seq_num=2の時は、「左右」の時にのみメッセージ。
 5回連続でメッセージ表示を繰り返したらってこと?
「『左右』の時」って「1回目が左で2回目が右」という意味では
ないらしいけど、それなら一体、何?

>その他の反応は記録だけを行う。
>これが5回連続表示まで繰り返して、seq_numの値を増やす。

>以下、繰り返し。

>seq_numの数は1〜6迄増加するように設定。
>seq_num=6の時のみ、10回連続メッセージが表示されたら、
>終了。
1+5×4+10=31回連続でメッセージを表示したら終了ってこと?



ANTARES

リンク

2008/3/26(Wed) 02:16:34|NO.14592

>>その他の反応は記録だけを行う。
> 何を記録するのですか?
 メッセージ表示を記録したときは、ここでいう「記録」はしないのですか?

 その記録は一体、何に使うのですか?
このゲーム中は使わない?

 先のことまで書くと、上のようにごちゃごちゃになるので、
とりあえず、今やりたいことだけをわかるように説明してください。



GOTOU

リンク

2008/3/26(Wed) 17:00:35|NO.14600

ANTARES様

分かりにくい説明で、申し訳ありません。

簡潔に表現すると、
指定した組み合わせ(例えば1回目に左、2回目に右)の反応をしたら、
メッセージを出すようにしたいのです。
メッセージを出したことも記録したいと考えています。

具体的には、
毎回の反応は全て記録しておき、
この例の場合は2回目の反応があった時に初めて、
2回の反応が「左右」だったかをチェックしたいのです。

>その記録は一体、何に使うのですか?
何回目に「左」か「右」か、いつ、メッセージを出したか、
という記録は、ゲーム中では使いません。
後で、ゲームの結果を見る時に、どこで、どんな風に間違えたのか、
を見るために使います。


蛇足かも知れませんが、前出の話を補足すると、
毎回の反応を数えているcountとは別に、
目的の系列の反応数を数えている変数(seq_count)を用意しておき、
2回の反応が「左右」の順で行われた場合が正解の時は、
2回目の反応の後にチェックを行います。

チェックした結果、2回の反応が、「左右」であればメッセージを表示し、
seq_countを0に戻して、反応の記録を再開します。
2回の反応が、「左右」以外の場合は、メッセージは表示させず、
seq_countを0に戻して、反応の記録を再開します。

ここまでが、第一段階。

以下は先のことですが、前出の話ですので、補足します。

メッセージを表示したら、
メッセージ表示の有無を数える変数(message_count)に1を代入し、
再び反応の記録を再開します。

次の2回(countは4回目、seq_countは2回目)に、
「左右」以外の反応だった場合は、メッセージは表示させず、
seq_countを0に戻して、反応の記録を再開します。

このとき、message_countには0を代入します。

message_countに1が連続5回続いたら、
次の条件(例えば、1回目に左、2回目に右、3回目に左)に移行します。



As

リンク

2008/3/26(Wed) 21:24:03|NO.14605

自分で組んだプログラムの流れを説明するよりもF1を使って、
ひとつひとつ今まで説明において提示したスクリプトを調べ尽くして自分のものにしてください。



naznyark

リンク

2008/3/27(Thu) 02:24:10|NO.14611

> さっぱりわかりません。

おそらくこんなことをやりたいのでは、と推測して作ってみたもの。
(左右判定は左クリック・右クリックの判定に単純化。)

#define BTN_LEFT 1 #define BTN_RIGHT 2 onclick gosub *cli dim clicklog, 1024 dim seq, 3, 3 seq( 0, 0 ) = BTN_LEFT seq( 0, 1 ) = BTN_LEFT, BTN_RIGHT seq( 0, 2 ) = BTN_LEFT, BTN_RIGHT, BTN_LEFT sdim dir, 64, 3 dir = "", "左", "右", "Level" level = 1 sublevel = 1 stop *cli if ( iparam == 0 ) { flag = BTN_LEFT } else : if ( iparam == 3 ) { flag = BTN_RIGHT } else { flag = 0 } title dir( flag ) clicklog( clickcount ) = flag clickcount += 1 clickcount0 += 1 if ( clickcount0 == level ) { clickcount0 = 0 : gosub *check } return *check f = 1 repeat level i = clickcount - level + cnt if ( clicklog( i ) == seq( cnt, level - 1 ) ) { clicklog( i ) |= 256 } else { f = 0 } loop if ( sublevel == 1 ) { color 255, 255, 255 : boxf : pos 0, 0 } if ( f ) { clicklog( clickcount - 1 ) |= 512 color 0, 0, 0 : mes "" + sublevel + "hit" sublevel += 1 if ( sublevel >= 4 ) { mes "next level" level += 1 sublevel = 1 clicklog( clickcount ) = ( level << 8 ) | 3 clickcount += 1 } } else { color 0, 0, 0 : mes "miss" sublevel = 1 } if ( level >= 4 ) { gosub *log : dialog "all clear" : stop } return *log pos 320, 0 repeat clickcount mes "" + dir( clicklog( cnt ) & 0xFF ) + " : " + ( clicklog( cnt ) >> 8 ) loop return



ANTARES

リンク

2008/3/27(Thu) 02:51:21|NO.14612

>おそらくこんなことをやりたいのでは、と推測して作ってみたもの。
>(左右判定は左クリック・右クリックの判定に単純化。)
 level 1は左左左
 level 2はバグっているとしか思えませんが……?

仕様を書かずに動かないスクリプトばかり書くGOTOUさん病がnaznyarkさんにうつった?

ちなみに、こないだまでnyanzarkさんだとばかり思ってました(^_^;;


>蛇足かも知れませんが、
 蛇足ばかりで要点が抜けています。
私はとりあえずリタイア。



SYAM

リンク

2008/3/27(Thu) 17:15:42|NO.14622

今更かもしれませんが
参考になるでしょうか?
※携帯からの投稿でしてミスありましたらごめんなさい
簡単な記憶ゲームです
お題の通りに矢印キーを押すと次に行きます。
※logとか消してないので適当にやってるといつかクラッシュすると思います。

screen 0,240,180,0 msg="":mesbox msg,240,180,0 log="" explen=2 *INIT exp="" repeat explen if rnd(2)=0:exp+="L":else:exp+="R" loop dialog exp,0,"お題" *KEY_WAIT stick k if (k&5)!=0:goto *BTN wait 1:goto *KEY_WAIT *BTN if k=1:log+="L" if k=4:log+="R" result=strmid(log,-1,explen):title result if result!=exp:goto *KEY_WAIT msg+=exp+" -Ok.":objprm 0,msg explen+=1 goto *INIT



As

リンク

2008/3/27(Thu) 18:11:53|NO.14629

なんだか質問が重複しててわかりにくくなってるのにも関わらず、
それでも解答してくれる・・・親切すぎますよ・・・笑

「左と右の交互クリック」の質問だったはずなのに、今では
「決められたパターンで正解を導きたい」という質問になってきています。

この場合は俗に言うスレ違い。新しい質問を立てて質問したほうがいいとおもいます。



SYAM

リンク

2008/3/27(Thu) 18:37:25|NO.14630

>「左と右の交互クリック」の質問だったはず
最初から、『入力の記録と入力パターン検出』の質問だったように見えました。
ファイルへの記録は示していませんが、入力パターンの記録と照合を含んだスクリプトを示したつもりです。
…勘違いしてますか私…??(汗)



GOTOU

リンク

2008/3/27(Thu) 23:03:22|NO.14643

ANTARES様
有り難うございます。
理解に努めます。

>ちなみに、こないだまでnyanzarkさんだとばかり思ってました(^_^;;
お気づきとは思いますが、別人です。
説明が至らず、ご迷惑をお掛けし、申し訳ございません。

As様
自分で試行錯誤して作るべきというご指摘、ごもっともです。
色々ご指摘頂き、有り難うございます。
新しい問題ごとにスレ立てするよう、以後気をつけます。

SYAM様
>最初から、『入力の記録と入力パターン検出』の質問だったように見えました
私の至らない説明から、ここまで理解頂き、有り難うございます。
実行してみたところ、私の作りたいものに可成近い仕様でした。
後は、ANTARES様、As様のご指摘通り、試行錯誤してみます。



As

リンク

2008/3/28(Fri) 01:01:30|NO.14644

>SYAMさん
ソースもだいぶ複雑なので今回はここでやったほうがいいかもしれませんね。
ただ、最初の頃では左か右かそれ以外か という順序をあらわすスクリプトを
最初に既に作ってあったんです。ただ、”左右左”というパターン判定については
別物だと思いますが。

>GOTOUさん
今提示してもらったこの二つのソーススクリプトをうまく掛け合わせてみてください。
・ボタンを押したときの記録
・パターンの判定



naznyark

リンク

2008/3/28(Fri) 01:56:42|NO.14645

>>(左右判定は左クリック・右クリックの判定に単純化。)
> level 1は左左左
> level 2はバグっているとしか思えませんが……?

>>(左右判定は左クリック・右クリックの判定に単純化。)
この説明が勘違いされた?
画面上の円をクリックするかわりにマウスの左右ボタンを
クリックしてください、という意味のつもりだったのだが・・・


なお私はGOTOUさんの意図しているものは以下のようなものでは
ないかと推測しました。

・決められた回数だけ操作(クリック)を行い、決められた組み合わせで
 操作していたら成功、そうでなければ失敗。
・連続n回成功すると次のレベルにあがり、操作しなくてはならない
 回数が増える。途中で失敗したら成功回数がリセットされる。
・すべての操作の履歴を取り後で利用する。


> ちなみに、こないだまでnyanzarkさんだとばかり思ってました(^_^;;
まあ変な名前だし(笑)。



ANTARES

リンク

2008/3/28(Fri) 02:14:58|NO.14646

 読み直してみたらNO.14600の前半は、けっこうわかりやすかったし、
後半もじっくり読めばわかったので、とりあえず復帰。
 でも、記録は無視。
 「seq_numの数は1〜6迄増加するように設定」というのも、
4〜6の正解数が不明なので無視。っていうか、正解数も4〜6と仮定して
(正解数を記憶する配列は不要と仮定して)3までしかやらない。
っていうか、んなもん、6までなんかやってられまへん。
 ミスしたらどうするということを全く書いてないのは何もしないということかと
思います。それじゃいかんだろと思うけど、そうすると話が進まないので
それでいいことにしました。


scrExp = 0 screen scrExp, ginfo_dispx, ginfo_dispy, 4, 0, 0;窓枠付き #define BTN_LEFT 1 #define BTN_RIGHT 2 #module #define rad double(3.14159265)/double(180) #deffunc box int x1, int y1, int x2, int y2 line x1,y1,x2,y1 line x1,y2 line x2,y2 line x2,y1 return #defcfunc redrect int _x,int _y,int size, int show_debug if show_debug = 1 { repeat 360 pset size+ginfo(22)+double(size)*sin(double(rad*cnt)),size+ginfo(23)+double(size)*cos(double(rad*cnt)) loop } px = size+ginfo(22) py = size+ginfo(23) if show_debug =1 { pset px , py pset _x, _y } if size>( sqrt(abs((px-_x)*(px-_x)+(py-_y)*(py-_y) ))) : return 1 return 0 #global onclick gosub *cli onexit gosub *exi data="" objsize 100,70 pos 10,0: listbox list,ginfo_winy,data idlist=stat scrWidth = ginfo_dispx scrHeight = ginfo_dispy poscircleX = (scrWidth / 2 - 100) poscircleY = scrHeight * 6 / 10 num=3 dim seq,num,num seq=BTN_LEFT seq(0,1)=BTN_LEFT, BTN_RIGHT seq(0,2)=BTN_LEFT, BTN_RIGHT, BTN_LEFT dim res,num sdim dir,10,3 dir="","左","右" notesel data size=100 xright=poscircleX+350 yright=poscircleY-200 xleft=poscircleX-250 yleft=poscircleY-200 color 255,150,150 circle xright,yright,xright+size,yright+size;right circle xleft,yleft,xleft+size,yleft+size;left y=0 stop *cli pos xleft,yleft res(count)=redrect(mousex,mousey,size/2,0) if res(count)==0 { pos xright,yright if redrect(mousex,mousey,size/2,0): res(count)=2 } count++ if count>seq_num { sq=seq_num+1 flag=1 repeat sq if res(cnt)!=seq(cnt,seq_num): flag=0: break loop if flag { msgcnt++ n=0 repeat sq n++ noteadd ""+sq+"-"+msgcnt+"-"+n+"回目 "+dir(res(cnt)) loop objprm idlist,data if msgcnt>4: seq_num++: msgcnt=0 } else { msgcnt=0 } count=0 } if seq_num<num: return dialog "cleared!!" *exi //notesel data //notesave dir_cur+"data.ini" end



SYAM

リンク

2008/3/28(Fri) 02:29:15|NO.14648

>Asさん
返答ありがとうございます。理解できたと思います。

>GOTOUさん
説明の仕方について。
「反応」という語が引っかかっていました。
作っておられるソフトにおいては、ユーザーからの入力がそういう意味を持っているのでしょうが、こちらはそのことを知りません。
なので、「反応」という 意味を表す 語から、「入力」という 具体的な動作を表す 語が浮かんできません。
そうなると、いったいどう動いて欲しいのか、見当もつかなくなります。

「反応」に限らず、何がしたいのか、どういう考えがあるのかが先に立ちすぎて、抽象的な意味を表す語が多くなっているようです。
「どう動いてほしいのか」を、具体的な動作を表す語で示すようにしたほうがよいでしょう。
というか、そうしないと伝わらない可能性が高いです。


ついでに。先に私が挙げたスクリプトについて簡単な解説をします。
考え方は、
「1回の入力を1文字で表す」
「複数回の入力はそれをつなげた文字列で表す」
です。
msg は、画面に出てくるメッセージの文字列です。
log は、それまでの入力を表す文字列です。
explen は、お題の文字列の長さです。2から始まって正解するごとに増えてますね。
exp は、お題の文字列です。最初のrepeatの中でランダムに作っています。
result は、logの末尾を(explen)文字だけ抽出したものです。

コメントはついていませんが、全体がそう長くないですし、ループや分岐も多くないので読むことは難しくないと思います。
この方法だと、今回やりたいこと(と思われること)の筆頭である複数回の入力の比較がいっぺんでできています。

しかし、今見たらOKのメッセージ末尾に \n を入れ忘れていました。 悔しい。



GOTOU

リンク

2008/3/28(Fri) 21:13:25|NO.14664

皆様
アドバイス有難うございます。
理解が中々追いつかず、きちんとしたスクリプトを書くまでに至らない為、
具体的なスクリプトに関する返信が出来ず、申し訳ございません。
まずは、理解に努めます。

As様
>今提示してもらったこの二つのソーススクリプトをうまく掛け合わせてみてください。
>・ボタンを押したときの記録
>・パターンの判定
有難うございます、頑張ります。

naznyark様
>・決められた回数だけ操作(クリック)を行い、決められた組み合わせで
> 操作していたら成功、そうでなければ失敗。
>・連続n回成功すると次のレベルにあがり、操作しなくてはならない
> 回数が増える。途中で失敗したら成功回数がリセットされる。
>・すべての操作の履歴を取り後で利用する。
ご説明頂き有難うございます、その通りです。

ANTARES様
有難うございます、理解に努めます。
前出ですが、
>・決められた回数だけ操作(クリック)を行い、決められた組み合わせで
> 操作していたら成功、そうでなければ失敗。
>・すべての操作の履歴を取り後で利用する。
この失敗の場合では、特にメッセージを出したりはせず、
再び決められた回数の操作が行われるまで待って、
決められた組み合わせでの操作か否かのチェックを行います。

SYAM様
説明の仕方についてのご指摘、有難うございました。
お察し頂いた通り、「反応」はユーザーからの「入力」の意味で使っていました。
誤解を招くような語彙を使わないで説明する必要がありました。
以後気をつけます。

スクリプトの解説も有難うございます。
構造をよく理解して、活かせるよう、頑張ります。



ANTARES

リンク

2008/3/29(Sat) 00:56:16|NO.14672

>この失敗の場合では、特にメッセージを出したりはせず、
>再び決められた回数の操作が行われるまで待って、
>決められた組み合わせでの操作か否かのチェックを行います。
 それを「何もしない」と言います。
では、何をするべきかは、明日か明後日にでも。
明日は休日出勤なので。



ANTARES

リンク

2008/3/31(Mon) 00:26:22|NO.14712


scrExp = 0 screen scrExp, ginfo_dispx, ginfo_dispy, 4, 0, 0;窓枠付き #define BTN_LEFT 1 #define BTN_RIGHT 2 #module #define rad double(3.14159265)/double(180) #defcfunc redrect int _x,int _y,int size, int show_debug if show_debug = 1 { repeat 360 pset size+ginfo(22)+double(size)*sin(double(rad*cnt)),size+ginfo(23)+double(size)*cos(double(rad*cnt)) loop } px = size+ginfo(22) py = size+ginfo(23) if show_debug =1 { pset px , py pset _x, _y } if size>( sqrt(abs((px-_x)*(px-_x)+(py-_y)*(py-_y) ))) : return 1 return 0 #global onclick gosub *cli onexit gosub *exi data="" objsize 100,70 pos 10,0: listbox list,ginfo_winy,data idlist=stat scrWidth = ginfo_dispx scrHeight = ginfo_dispy poscircleX = (scrWidth / 2 - 100) poscircleY = scrHeight * 6 / 10 num=3 dim seq,num,num seq=BTN_LEFT seq(0,1)=BTN_LEFT, BTN_RIGHT seq(0,2)=BTN_LEFT, BTN_RIGHT, BTN_LEFT dim res,num sdim dir,10,3 dir="","左","右" notesel data size=100 xright=poscircleX+350 yright=poscircleY-200 xleft=poscircleX-250 yleft=poscircleY-200 color 255,150,150 circle xright,yright,xright+size,yright+size;right circle xleft,yleft,xleft+size,yleft+size;left y=0 boxw=100: boxb=20: fby=64 gosub *lFeedbackInit gosub *lFeedbackDraw stop *cli pos xleft,yleft res(count)=redrect(mousex,mousey,size/2,0) if res(count)==0 { pos xright,yright if redrect(mousex,mousey,size/2,0): res(count)=2 } if res(count)==seq(count,seq_num) { i=count: gosub *lBlueBox } else { i=count: gosub *lRedBox } count++ if count>seq_num { sq=seq_num+1 flag=1 repeat sq if res(cnt)!=seq(cnt,seq_num): flag=0: break loop if flag { msgcnt++ n=0 repeat sq n++ noteadd ""+sq+"-"+msgcnt+"-"+n+"回目 "+dir(res(cnt)) loop objprm idlist,data if msgcnt>4 { seq_num++ msgcnt=0 gosub *lFeedbackInit gosub *lFeedbackDraw } } else { msgcnt=0 } count=0 } if seq_num<num { n=seq_num+1 repeat n if (count+n-1)\n!=cnt: i=cnt: gosub*lGrayBox loop return } dialog "cleared!!" *exi //notesel data //notesave dir_cur+"data.ini" end *lFeedbackInit fbx=(ginfo_winx-(seq_num+1)*boxw-seq_num*boxb)/2 return *lFeedbackDraw color 255,255,255: boxf 0,fby,ginfo_winx,fby+boxw repeat seq_num+1 i=cnt: gosub *lGrayBox x+=boxw+boxb loop return *lBlueBox color 0,0,255 goto *lBox *lRedBox color 255,0,0 goto *lBox *lGrayBox color 128,128,128 *lBox x=(boxw+boxb)*i+fbx boxf x,fby,x+boxw,fby+boxw return



GOTOU

リンク

2008/3/31(Mon) 17:55:01|NO.14735

ANTARES様

有り難うございます。
「何もしない」ときに何をすべきか、少し理解出来ました。
きちんと理解出来るよう、これから努めます。
頂いたスクリプトでやりたいことの殆どが実現出来ています。
後は自分で試行錯誤しながら頑張ります。

皆様、お忙しい中本当に有り難うございました。



ANTARES

リンク

2008/3/31(Mon) 21:42:37|NO.14738

 最後に記録について。

 配列resは現在のseq_num,msgcntについてしか記憶していませんが、
これをすべてのseq_num,msgcntについて記憶できるようにし
(これは3次元配列にすればいいだけ)、
さらに、プレイヤーが間違えたシリーズについても記憶できるように
する必要がありますが、これが難しい。
これができれば、この配列をbsaveするだけでOKです。

 すぐに思いつくのはseries次元を増やして4次元配列にすることですが、
プレイヤーが何回間違えるか予測できないのでseriesの最大値をいくつにすれば
いいかわからないという点が大きな壁です。HSPの自動拡張に期待することも
できますが、要素数が大きくなるとバグるんじゃないかという不安が
私にはあります。

 また、必ず最大値だけ間違うと決まっているわけでもないので、
非常に無駄が多くなります。無駄をなくすには3次元のままで、
countとseriesを合体することが考えられます。
つまり、countは配列の添え字としては使わず、単に何回連続で正解したかの
カウンタにのみ使い、seriesはres配列の添え字として使い、プレイヤーが
間違えても正解してもカウントアップし、5回連続正解したときだけ
ゼロクリアします。これでもまだ無駄は残りますが、配列を使う限り、
最小限の無駄と言えるでしょう

 1次元配列にしてしまうという荒技ならもっと無駄を減らせますが、
各seq_numやmsgcntがどこから始まるかを記憶しなければならないので、
かなり複雑になります。



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