キーボード入力について。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
かるた

キーボード入力について。

#1

投稿記事 by かるた » 1年前

 昨日からお世話になっております。かるたと申します。
 簡単な脳トレゲームが作りたくて奮闘しております。
今日は、ランダムな計算問題を作って、計算問題を表示した後、それに対してキーボード入力で答えを入力し、
〇か×を出力するプログラムを作っておりました。
 ところが、計算問題を表示した後、すぐに〇が表示されてしまいます。
例えば、プレイヤーがキーボードで「0」と入力することを考えた場合、switch文でcase0として

コード: 全て選択

switch("問題の答え"){
if (KEY_INPUT_0)

					DrawFormatString(200, 300, Green, "〇 ");
						 else
							 DrawFormatString(200, 300, Green, "× ");
}
と僕は考えました。しかし、何も押さなくても〇と出力されます。
ソースコードは、

コード: 全て選択

#include "DxLib.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	int Key[256]; // キーが押されているフレーム数を格納する

				  // キーの入力状態を更新する




	ChangeWindowMode(TRUE);          // ウインドウモードに変更
	if (DxLib_Init() == -1) return -1; //DXライブラリ初期化 エラーが起きたら終了 
	int Random[2]; //乱数の配列を二つ用意
	int Green = GetColor(0, 255, 0);
	int x;//二つの乱数を合計した数の変数を用意
	SRand(10);                          //乱数の初期値を10で設定。
	Random[0] = GetRand(5);
	Random[1] = GetRand(4);


	int StartTime;  //今の時間
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK);

	bool displayText = true;//計算問題の文字を表示するか
	bool displayText2 = false;//回答の文字を表示するか

	// 文字を表示するか
	StartTime = GetNowCount(); // プログラムの開始時刻

	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {

		if (displayText)
		{
			DrawFormatString(200, 200, Green, "%d + %d = ", Random[0], Random[1]);
			if (GetNowCount() - StartTime >= 6000)
			{
				// 6秒経ったら文字を表示しなくする
				displayText = false;

			}
		}


		if (displayText == 0) { //乱数の足し算の表示が消えた後
			displayText2 = true;

			if (displayText2) {
				DrawFormatString(200, 200, Green, "計算の答えを入力しなさい。");

				x = Random[0] + Random[1];
				switch (x) {

				case 0:  if (KEY_INPUT_0)
					DrawFormatString(200, 300, Green, "〇 ");
						 else
							 DrawFormatString(200, 300, Green, "× ");

				case 1:if (KEY_INPUT_1)
					DrawFormatString(200, 200, Green, "〇");
					   else
						   DrawFormatString(200, 300, Green, "× ");
					break;

				case 2:if (KEY_INPUT_2)
					DrawFormatString(200, 300, Green, "〇 ");
					   else
						   DrawFormatString(200, 300, Green, "× ");
					break;

				case 3:if (KEY_INPUT_3)
					DrawFormatString(200, 300, Green, "〇 ");
					   else
						   DrawFormatString(200, 300, Green, "×");

					break;

				case 4:if (KEY_INPUT_4)
					DrawFormatString(200, 300, Green, "〇");
					   else
						   DrawFormatString(200, 300, Green, "×");
					break;

				case 5:if (KEY_INPUT_5)
					DrawFormatString(200, 300, Green, "〇 ");
					   else
						   DrawFormatString(200, 300, Green, "× ");
					break;

				case 6:if (KEY_INPUT_6)
					DrawFormatString(200, 300, Green, "〇 ");
					   else
						   DrawFormatString(200, 300, Green, "×");
					break;

				case 7:if (KEY_INPUT_7)
					DrawFormatString(200, 300, Green, "〇");
					   else
						   DrawFormatString(200, 300, Green, "× ");
					break;

				case 8:if (KEY_INPUT_8)
					DrawFormatString(200, 300, Green, "〇 ");
					   else
						   DrawFormatString(200, 300, Green, "× ");
					break;

				case 9:if (KEY_INPUT_9)
					DrawFormatString(200, 300, Green, "〇 ");
					   else
						   DrawFormatString(200, 300, Green, "×");
					break;
				}
			                   
			
			        }
		    }

	}
	WaitKey();
	DxLib_End();        // DXライブラリ使用の終了処理

	return 0;        // ソフトの終了r

}
です。よろしくお願いします。

アバター
keito94
記事: 264
登録日時: 1年前
連絡を取る:

Re: キーボード入力について。

#2

投稿記事 by keito94 » 1年前

もしかして、

コード: 全て選択

if(Key[入力するキー])
ではないのでしょうか?
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

かるた

Re: キーボード入力について。

#3

投稿記事 by かるた » 1年前

keito94さん回答ありがとうございます。
switch文の中身を(Key[KEY_INPUT_])に変えたのですが、〇がすぐに表示されます。
キー入力したものが合計値と一緒なら〇を出力したいのですが・・・

アバター
みけCAT
記事: 6003
登録日時: 7年前
住所: 千葉県
連絡を取る:

Re: キーボード入力について。

#4

投稿記事 by みけCAT » 1年前

かるた さんが書きました:switch文の中身を(Key[KEY_INPUT_])に変えたのですが、〇がすぐに表示されます。
Keyが明示的に初期化されていない自動変数となっているので、値は不定です。
キーの状態を取得してKeyに格納する処理が必要です。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: キーボード入力について。

#5

投稿記事 by かずま » 1年前

次のようコードを修正してみました。

コード: 全て選択

    if (displayText2) {
        DrawFormatString(200, 200, Green, "計算の答えを入力しなさい。");
        static int ki[10] = {
            KEY_INPUT_0, KEY_INPUT_1, KEY_INPUT_2, KEY_INPUT_3, KEY_INPUT_4,
            KEY_INPUT_5, KEY_INPUT_6, KEY_INPUT_7, KEY_INPUT_8, KEY_INPUT_9,
        };
        char Buf[256];
        GetHitKeyStateAll(Buf);
        x = Random[0] + Random[1];
        if (Buf[ki[x]])
            DrawFormatString(200, 300, Green, "〇 ");
        else
            DrawFormatString(200, 300, Green, "× ");
    }
私の環境では、Srand(10) の下で常に 3 + 2 = が表示され、
5 のキーを押している間だけ、〇 が表示されました。
while ループは 1/60 秒ごとに実行されるので、表示は常に更新され、
キーを押すのをやめると、× の表示に変わります。

int Key[256]; が用意されていても、そこには何の値も設定されていません。
そこで、char Buf[256]; を用意し、GetHitKeyStateAll(Buf); で現在のすべての
キーの状態を取得したということです。

かずま

Re: キーボード入力について。

#6

投稿記事 by かずま » 1年前

int Key[256]; があったので、全部のキーの状態を取得する GetHitKeyAll を
使ってみましたが、よく考えてみると、問題の正解に対応するキーが押されて
いるかどうかだけを見ればよいので、CheckHitKey が使えます。

コード: 全て選択

    if (displayText2) {
        DrawFormatString(200, 200, Green, "計算の答えを入力しなさい。");
        static int ki[10] = {
            KEY_INPUT_0, KEY_INPUT_1, KEY_INPUT_2, KEY_INPUT_3, KEY_INPUT_4,
            KEY_INPUT_5, KEY_INPUT_6, KEY_INPUT_7, KEY_INPUT_8, KEY_INPUT_9,
        };
        x = Random[0] + Random[1];
        if (CheckHitKey([ki[x]])
            DrawFormatString(200, 300, Green, "〇 ");
        else
            DrawFormatString(200, 300, Green, "× ");
    }
でも、本当にこんな仕様でいいのですか?
まだ解答を入力する前に × が表示されていてかまわないのですか?
プログラムを変更して、6 + 9 = なんて問題を出すようにしたいとき、
1 と 5 のキーが連続して押されるのをチェックするんですか?

かるた

Re: キーボード入力について。

#7

投稿記事 by かるた » 1年前

先日からお世話になっております。かずまさん。

はい。はじめから×が出ているのは、だめです。
プレイヤーがキー入力したら〇か×が出力されるような仕様を教えていただきたいです。

後、2桁の場合もできれば教えていただけたらと思います。

本当に昨日からありがとうございます。

かずま

Re: キーボード入力について。

#8

投稿記事 by かずま » 1年前

かるた さんが書きました:プレイヤーがキー入力したら〇か×が出力されるような仕様を教えていただきたいです。
仕様は、「プレイヤーがキー入力したら〇か×が出力される」ですね。
その仕様を実現するアルゴリズム(さらにはコード)を教えてほしいということですね。

displayText2 を活用しましょう。
間違ったキー入力もチェックしないといけないので、GetHitKeyStateAll を使います。

また、SRand で 10 を設定せず、毎回異なる問題が作れるようにしたり、
DxLib_Init を 2回実行するのをやめたりもしました。

コード: 全て選択

#include "DxLib.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    ChangeWindowMode(TRUE);            // ウインドウモードに変更
    if (DxLib_Init() == -1) return -1; // DXライブラリ初期化 エラーが起きたら終了 
    SetDrawScreen(DX_SCREEN_BACK);

    int Green = GetColor(0, 255, 0);
    bool displayText = true;       // 計算問題の文字を表示するか
    bool displayText2 = false;     // 解答の文字を表示するか
    int answer = -1;               // 入力された解答

    int StartTime = GetNowCount(); // プログラムの開始時刻
    SRand(StartTime);              // 乱数の初期値を設定

    int Random[2];                 // 乱数の配列を二つ用意
    Random[0] = GetRand(5);
    Random[1] = GetRand(4);
    int x = Random[0] + Random[1]; // 二つの乱数を合計した数

    while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
        if (displayText) {
            DrawFormatString(200, 200, Green, "%d + %d =", Random[0], Random[1]);
            if (GetNowCount() - StartTime >= 6000) {
                displayText = false; // 6秒経ったら文字を表示しなくする
            }
        }
        else { // 乱数の足し算の表示が消えた後
            DrawFormatString(200, 200, Green, "計算の答えを入力しなさい。");
            static int ki[10] = {
                KEY_INPUT_0, KEY_INPUT_1, KEY_INPUT_2, KEY_INPUT_3, KEY_INPUT_4,
                KEY_INPUT_5, KEY_INPUT_6, KEY_INPUT_7, KEY_INPUT_8, KEY_INPUT_9,
            };
            char Buf[256];
            GetHitKeyStateAll(Buf);
            for (int i = 0; i < 10; i++) {
                if (Buf[ki[i]]) {
                    displayText2 = true;
                    answer = i;
                    break;
                }
            }
            if (displayText2) {
                DrawFormatString(200, 250, Green, "%d", answer);
                if (answer == x)
                    DrawFormatString(200, 300, Green, "〇 ");
                else
                    DrawFormatString(200, 300, Green, "× ");
            }
        }
    }

    DxLib_End();     // DXライブラリ使用の終了処理
    return 0;        // ソフトの終了r
}

かるた

Re: キーボード入力について。

#9

投稿記事 by かるた » 1年前

ありがとうございます。かずまさん。僕が望んでいた仕様です。それに読みやすい!!
ただ、自分初心者なので、分からない箇所があります。

コード: 全て選択

static int ki[10] = {
                KEY_INPUT_0, KEY_INPUT_1, KEY_INPUT_2, KEY_INPUT_3, KEY_INPUT_4,
                KEY_INPUT_5, KEY_INPUT_6, KEY_INPUT_7, KEY_INPUT_8, KEY_INPUT_9,
            };
            char Buf[256];
            GetHitKeyStateAll(Buf);
のところを詳しく教えていただけたら幸いです。
僕は、c言語のIf文、for文、配列を理解しているレベルの知識しかありません。

かずま

Re: キーボード入力について。

#10

投稿記事 by かずま » 1年前

かるた さんが書きました:c言語のIf文、for文、配列を理解しているレベルの知識しかありません。
bool、true、false というキーワードを使っているということは、
使用している言語は、C ではなく、C++ です。

配列は、理解しているんですよね。
宣言時に、= { ... } で初期化できるのが解らないのですか?

関数やブロックの中で変数を宣言すると、自動変数になり、
そこを通るたびに毎回初期化が実行されます。

static を付けると、静的変数となり、初期化は 1回だけになります。
というより、この場合、コンパイル時に初期値が割り当てられていて、
初期化の実行はないでしょう。

DxLib のリファレンスマニュアルをよく読みましょう。
GetHitKeyStateAllに詳しく解説されています。

かるた

Re: キーボード入力について。

#11

投稿記事 by かるた » 1年前

返信ありがとうございます。
マニュアルをしっかり読んで学習します。

返信

“C言語何でも質問掲示板” へ戻る