トップページ > 過去ログ > 記事閲覧
キー入力について
名前:TKOZ 日時: 2008/10/01 13:31

今、作っている野球ゲームのテストプログラムを 作成しているのですが、キー入力部分にバグが あると思い、コンソールプログラムを作成しました。 しかし、何故か、キー入力判定が連続して表示 されてしまいます。 これを、なんとか、1回のみに抑えたいのですが、 誰か、ご教授お願いします。 ソースコードを下記に記します。 #include<stdio.h> #include<windows.h> int timer(void); int Type(void); int keyflag=0; int main(void) { int nokori=11; int num=0; int Flag=1; while(Flag) { if(timer()==1) { nokori--; if(nokori<0) nokori=0; printf("残り時間は%d秒です。\n",nokori); } //printf("数値を入力してください。->\n"); num=Type(); if(num) { nokori=11; printf("%dの数字が入力されました。\n",num); } } } int timer(void) { static long BiginT; static long LatestT; static int flag=0; if(flag==0) { BiginT=GetTickCount(); flag=1; } if(flag==1) { LatestT=GetTickCount(); if(LatestT-BiginT>1000) { flag=0; return 1; } else { return 0; } } return 0; } int Type(void) { static int t[9]={0}; if(!t[0] && GetAsyncKeyState(VK_NUMPAD1)<0) { //keyflag=1; return 1; } if(!t[1] && GetAsyncKeyState(VK_NUMPAD2)<0) { //keyflag=1; return 2; } if(!t[2] && GetAsyncKeyState(VK_NUMPAD3)<0) { //keyflag=1; return 3; } if(!t[3] && GetAsyncKeyState(VK_NUMPAD4)<0) { //keyflag=1; return 4; } if(!t[4] && GetAsyncKeyState(VK_NUMPAD5)<0) { //keyflag=1; return 5; } if(!t[5] && GetAsyncKeyState(VK_NUMPAD6)<0) { //keyflag=1; return 6; } if(!t[6] && GetAsyncKeyState(VK_NUMPAD7)<0) { //keyflag=1; return 7; } if(!t[7] && GetAsyncKeyState(VK_NUMPAD8)<0) { //keyflag=1; return 8; } if(!t[8] && GetAsyncKeyState(VK_NUMPAD9)<0) { //keyflag=1; return 9; } t[0]=GetAsyncKeyState(VK_NUMPAD1)<0; t[1]=GetAsyncKeyState(VK_NUMPAD2)<0; t[2]=GetAsyncKeyState(VK_NUMPAD3)<0; t[3]=GetAsyncKeyState(VK_NUMPAD4)<0; t[4]=GetAsyncKeyState(VK_NUMPAD5)<0; t[5]=GetAsyncKeyState(VK_NUMPAD6)<0; t[6]=GetAsyncKeyState(VK_NUMPAD7)<0; t[7]=GetAsyncKeyState(VK_NUMPAD8)<0; t[8]=GetAsyncKeyState(VK_NUMPAD9)<0; return 0; }

Page: 1 |

Re: キー入力について ( No.1 )
名前:TKOZ 日時:2008/10/01 14:19

なお、このプログラムは、NumLockされていないと キー入力を受け付けません。注意してください。
Re: キー入力について ( No.2 )
名前:Will 日時:2008/10/01 18:34

コメントなしのソースを解析するのは大変です。 > if(!t[0] && GetAsyncKeyState(VK_NUMPAD1)<0) tとのANDで押下としている理由は何ですか? 以下、推察による回答(的外れの場合はご容赦願う) キーの押し続けを回避するためにチェックしているのであれば、 押された時にもtを更新しないと上記のifは押されている間必ず真になります。 修正するとしたら以下のような感じでしょうか。 static int t[9]={0}; int ret = 0; do { if(!t[0] && GetAsyncKeyState(VK_NUMPAD1)<0) { ret = 1; break; } 省略 } while(0); t[0]=GetAsyncKeyState(VK_NUMPAD1)<0; t[1]=GetAsyncKeyState(VK_NUMPAD2)<0; t[2]=GetAsyncKeyState(VK_NUMPAD3)<0; t[3]=GetAsyncKeyState(VK_NUMPAD4)<0; t[4]=GetAsyncKeyState(VK_NUMPAD5)<0; t[5]=GetAsyncKeyState(VK_NUMPAD6)<0; t[6]=GetAsyncKeyState(VK_NUMPAD7)<0; t[7]=GetAsyncKeyState(VK_NUMPAD8)<0; t[8]=GetAsyncKeyState(VK_NUMPAD9)<0; return ret;
Re: キー入力について ( No.3 )
名前:TKOZ 日時:2008/10/01 19:39

ソースコードを上のとおりに改良したら、 うまくいきました。 ありがとうございました。
Re: キー入力について ( No.4 )
名前:TKOZ 日時:2008/10/02 09:14

もうひとつ質問です、キーを離した時に、retが0に上書き されるのを防ぐには、どうすればいいですか?
Re: キー入力について ( No.5 )
名前:Will 日時:2008/10/02 12:45

質問の意図が良くわかりません。 Type関数の戻り値は ・何も押されていないときは0を返す ・キーが押されたときに押された数字を返す ・押し続けているときは0を返す ですよね。 であるならば、キーを離したときに0となるのは間違いでは無いと思いますが。
Re: キー入力について ( No.6 )
名前:TKOZ 日時:2008/10/02 14:37

すみません、本体のプログラムである 野球ゲームにその関数を使ってみたら、 うまくいかなかったのです。 なので、Type関数の仕様変更です。 Type関数の戻り値は、 ・前回何も押されていなくて、今回押されたら  押された数字を返す ・キーが離されても、キー入力されてなければ、  前回押された数字を返す ・引数int *keyflagが1ならば、0を返し、何も  押されていない状態にする、そして、  *keyflagを0にする 分かりにくい説明ですみません。
Re: キー入力について ( No.7 )
名前:Will 日時:2008/10/02 18:03

条件付けに不備があるような気がします。 例えば、以下のように操作した場合最後のretがどの値になることを希望していますか? 1を押す  → ret = 1; 押し続ける → ret = 0; 3も押す  → ret = 3; 押し続ける → ret = 0; 1だけ離す → ret = 0 or 1 or 3??? > 前回押された数字を返す これを素直に解釈すれば3だけど、そうすると3を離したときにも3になるから、 3が2回返ることになりますけど。 あとキーを離すのと、違うキーを押すのが同時の場合、押したキーの値が返るで正しいですか?
Re: キー入力について ( No.8 )
名前:TKOZ 日時:2008/10/02 20:15

>1だけ離す → ret = 0 or 1 or 3??? 3を希望します。 >あとキーを離すのと、違うキーを押すのが同時の場合、押したキーの値が返るで正しいですか? はい、結構です。
Re: キー入力について ( No.9 )
名前:Will 日時:2008/10/03 10:24

以下でどうでしょうか。 3番目の条件は大して難しくないのでそちらで実装してください。 static int t[9]={0}; int ret = 0; static int last_key = 0; do { // 今回押された場合のチェック if(!t[0] && GetAsyncKeyState(VK_NUMPAD1)<0) { last_key = ret = 1; break; } 省略 // 今回離された場合のチェック if ((t[0] && !(GetAsyncKeyState(VK_NUMPAD1)<0)) || // 途中省略 (t[8] && !(GetAsyncKeyState(VK_NUMPAD9)<0))) { ret = last_key; } } while(0);
Re: キー入力について ( No.10 )
名前:TKOZ 日時:2008/10/05 14:56

質問です。 上のソースは、このように記述すればいいのでしょうか? static int t[9]={0}; int ret = 0; static int last_key = 0; do { // 今回押された場合のチェック if(!t[0] && GetAsyncKeyState(VK_NUMPAD1)<0) { last_key = ret = 1; break; } if(!t[1] && GetAsyncKeyState(VK_NUMPAD2)<0) { last_key = ret = 2; break; } if(!t[2] && GetAsyncKeyState(VK_NUMPAD3)<0) { last_key = ret = 3; break; } if(!t[3] && GetAsyncKeyState(VK_NUMPAD4)<0) { last_key = ret = 4; break; } if(!t[4] && GetAsyncKeyState(VK_NUMPAD5)<0) { last_key = ret = 5; break; } if(!t[5] && GetAsyncKeyState(VK_NUMPAD6)<0) { last_key = ret = 6; break; } if(!t[6] && GetAsyncKeyState(VK_NUMPAD7)<0) { last_key = ret = 7; break; } if(!t[7] && GetAsyncKeyState(VK_NUMPAD8)<0) { last_key = ret = 8; break; } if(!t[8] && GetAsyncKeyState(VK_NUMPAD9)<0) { last_key = ret = 9; break; } // 今回離された場合のチェック if ((t[0] && !(GetAsyncKeyState(VK_NUMPAD1)<0)) || (t[1] && !(GetAsyncKeyState(VK_NUMPAD2)<0)) || (t[2] && !(GetAsyncKeyState(VK_NUMPAD3)<0)) || (t[3] && !(GetAsyncKeyState(VK_NUMPAD4)<0)) || (t[4] && !(GetAsyncKeyState(VK_NUMPAD5)<0)) || (t[5] && !(GetAsyncKeyState(VK_NUMPAD6)<0)) || (t[6] && !(GetAsyncKeyState(VK_NUMPAD7)<0)) || (t[7] && !(GetAsyncKeyState(VK_NUMPAD8)<0)) || (t[8] && !(GetAsyncKeyState(VK_NUMPAD9)<0))) { ret = last_key; } } while(0); t[0]=(GetAsyncKeyState(VK_NUMPAD1)<0); t[1]=(GetAsyncKeyState(VK_NUMPAD2)<0); t[2]=(GetAsyncKeyState(VK_NUMPAD3)<0); t[3]=(GetAsyncKeyState(VK_NUMPAD4)<0); t[4]=(GetAsyncKeyState(VK_NUMPAD5)<0); t[5]=(GetAsyncKeyState(VK_NUMPAD6)<0); t[6]=(GetAsyncKeyState(VK_NUMPAD7)<0); t[7]=(GetAsyncKeyState(VK_NUMPAD8)<0); t[8]=(GetAsyncKeyState(VK_NUMPAD9)<0); return ret;
Re: キー入力について ( No.11 )
名前: 日時:2008/10/06 01:41

うーん、どんな場合のキー情報がほしいのか 微妙ですが、GetAsyncKeyState関数によって ・現在押されている ・前回呼び出し次以降に1回以上押された ・現在押されていて過去に押されたことがある この三つが区別できることは分かっていますか? 「現在押されている」場合のみに処理すれば いいように思えるのですが?
Re: キー入力について ( No.12 )
名前:TKOZ 日時:2008/10/06 20:33

通さん >この三つが区別できることは分かっていますか? 一応、分かっているつもりです。 >「現在押されている」場合のみに処理すれば >いいように思えるのですが? それが、うまくいかないんですよ。 現在のソースファイル ttp://www.geocities.jp/tkoz2007/baseball_test_06.zip をダウンロードしてくれれば分かります。 キー入力関数int InputNumPitcher(void);と int InputNumBatter(void);は、順番にも寄りますが、 常に値が代入されていないといけないので、 0を返すとまずいんですよ。 値をフラグで管理して、保存しておく方法も考えた のですが、うまくいきませんでした。

Page: 1 |