タイピングゲーム 入力動作に関して

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Ken2929
記事: 6
登録日時: 1年前

タイピングゲーム 入力動作に関して

#1

投稿記事 by Ken2929 » 1年前

ゲーム制作で困っています。

まずこのソースコードで現状できている事としてはまずランダムでcsvの中にある文字列を呼び出し出力させて(ローマ字もセット)制限時間60秒までのカウントダウン、60秒経過すれば終了するというプログラムとなってます。

問題は、入力した部分を赤く塗りつぶし、間違ったところだけ青で出力して最後の文字列まで入力しきった瞬間次のお題に勝手に飛びたいのが理想で、60秒経過後、入力した数、間違って入力した数、秒間平均打数を出力したいと考えてますがどうにも上手く行かず困っています。

プログラム作るのは経験なくて初心者という立場になりますが、どういう風に改善するべきか何卒ご指摘ご指導のほどお願いします!

開発環境は
visualstudio2022 DXライブラリを使用したC++です。

コード:

/* ヘッダファイル ---------------------------------------------------------------------------- */
#include "DxLib.h"

/* 記号定数(マクロ) */
#define SIZE 30

/* エントリポイント -------------------------------------------------------------------------- */
// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    //ウィンドウモードを変更
    ChangeWindowMode(TRUE);

    //背景色を黒
    SetBackgroundColor(0, 0, 0);

    //DXライブラリ初期化処理
    if (DxLib_Init() < 0) return -1;


    //文字配列
    char Disp_Char[SIZE][40];           //表示文字列
    char Typing_Char[SIZE][30];         //打つ文字列

    int Typing_Num[50];

    const char mozi3[30] = { 'a','i','u','e','o','k','s','t','n','h','m','y','r','w','\0' };    //正解判定文字列

    //表示させる文字データを読込む
    int FileHandle;
    FileHandle = FileRead_open(".\/data/01.表示文字.csv");
    for (int i = 0; i < SIZE; i++) {
        FileRead_gets(Disp_Char[i], 50, FileHandle);
    }
    FileRead_close(FileHandle);
    FileRead_close(FileHandle);
    FileHandle = FileRead_open(".\/data/03.打つ文字.csv");
    for (int i = 0; i < SIZE; i++) {
        FileRead_gets(Typing_Char[i], 50, FileHandle);
    }
    FileRead_close(FileHandle);

    //表示
    DrawString(0, 0, "J1 やさしい ゲームタイピング画面です。", GetColor(255, 255, 255));
    DrawString(0, 20, "Escキー又はBackSpaceを押すとメニュー画面に戻ります。", GetColor(255, 255, 255));
    DrawString(0, 40, "Spaceキーを押すとゲームが開始されます。", GetColor(255, 255, 255));

    //スペースキーが押されるまで
    while (1) {
        if (CheckHitKey(KEY_INPUT_SPACE) == 1) {
            break;
        }
    }


    int Rand_Num = 0;
    Rand_Num = GetRand(SIZE);

    DATEDATA Date;
    int StartTime;

    //現在時刻の入手
    GetDateTime(&Date);

    //現在経過時間の入手
    StartTime = GetNowCount();

    //計測開始から60秒が過ぎるまでループ 
    while (GetNowCount() - StartTime < 60000)
    {
        //最初に表示される黒文字
        SetFontSize(30);
        DrawString(150, 200, Disp_Char[Rand_Num], GetColor(255, 255, 255));
        DrawString(150, 250, Typing_Char[Rand_Num], GetColor(255, 255, 255));


        char String[2];
        char InputChar;

        char mo;
        int i = 0;

        // 入力される文字を随時画面中央に描画します
        while (1) {

            String[1] = 0;
            // ESCキーが押されるか、何らかの内部エラーが発生するまでループする
            while (!ProcessMessage() && (CheckHitKey(KEY_INPUT_ESCAPE) == 0)) {
                ClearDrawScreen();
                //表示
                SetFontSize(18);
                DrawString(0, 0, "J1 やさしい ゲームタイピング画面です。", GetColor(255, 255, 255));
                DrawFormatString(0, 60, GetColor(255, 255, 255), "残り:%d秒", (60000 - (GetNowCount() - StartTime)) / 1000);
                //最初に表示される黒文字
                SetFontSize(30);
                DrawString(150, 200, Disp_Char[Rand_Num], GetColor(255, 255, 255));
                DrawString(150, 250, Typing_Char[Rand_Num], GetColor(255, 255, 255));
                //InputAnswerに格納されている答えの文字と比較して一致するまで入力させる
                InputChar = GetInputChar(TRUE);
                if (InputChar != 0 && InputChar >= CTRL_CODE_CMP) {
                    String[0] = InputChar;
                    String[1] = '\0';
                    if (String[0] == mozi3[i]) {
                        break;
                    }

                }
                //計測開始から60秒が過ぎるまでループ 
                if (GetNowCount() - StartTime > 60000) {
                    break;
                }
            }

            //計測開始から60秒が過ぎるまでループ 
            if (GetNowCount() - StartTime > 60000) {
                break;
            }

            //正しく打てた文字を描画(赤色に変更します)
            DrawString(i * 100 + 50, 300, Disp_Char[i], GetColor(255, 0, 0));
            DrawString(i * 100 + 70, 350, Typing_Char[i], GetColor(255, 0, 0));

            //次の文字に移るため
            //i++;
        }
        //WaitTimer(2000);
        //WaitKey();        // キー入力待ち
        DxLib_End();    // DXライブラリ使用の終了処理
        return 0;        // ソフトの終了     
    }
}

アバター
usao
記事: 1887
登録日時: 11年前

Re: タイピングゲーム 入力動作に関して

#2

投稿記事 by usao » 1年前

> ……したいと考えてますがどうにも上手く行かず困っています

これで赤の他人にあなたの抱えている問題が伝わると思いますか?
「上手く行かない」とだけ言われても読み手にとっては情報量ゼロに等しいです.

……というような事柄をまずはちゃんと考えてください.
このような場所で質問する際だけでなく,プログラムを作る際にも同様に.
すなわち,あるべき動作とは何か? というような事柄を,まずはあなた自身があなた自身に対して「実装できるレベルの具体性を有する説明」を行うことから始めてください.

「間違ったところ」 だとか 「入力しきった瞬間」 だとかいうのでは曖昧すぎます.
「間違った」とは? 「入力しきった」とは?

それができないなら,そもそも実装できるわけがないので.


で,例えば【そうはいっても,「間違った」ということを一体どうやって判定すればよいのだろうか? というところがわからない】とかいう場合には,そのような具体的な内容に関する質問をすると良いでしょう.
もちろんその際には
あなたのプログラムが正解のデータや入力された内容というのをどのようなデータ形式で保持しているのか,等々の説明を行わねばなりません.

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

Re: タイピングゲーム 入力動作に関して

#3

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

とりあえずループが何個もあってこんがらがっているようなので、状態変数を使った典型的な制御方法に直してみました。
これだけではうまく動きません。
また、
  • もとのプログラムではEscキーを押すと赤い文字が表示されるが、このプログラムはEscキーを押すと終了する
  • もとのプログラムではウィンドウを閉じてもしばらくプロセスが残るが、このプログラムではすぐにプロセスが終了する
というふうに動作が変わっています。

コード:

/* ヘッダファイル ---------------------------------------------------------------------------- */
#include "DxLib.h"

/* 記号定数(マクロ) */
#define SIZE 30

/* 状態 */
enum Status {
	STATUS_TITLE_INIT,
	STATUS_TITLE,
	STATUS_GAME_INIT,
	STATUS_GAME,
	STATUS_RESULT_INIT,
	STATUS_RESULT,
};

/* エントリポイント -------------------------------------------------------------------------- */
// プログラムは WinMain から始まります
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    //ウィンドウモードを変更
    ChangeWindowMode(TRUE);

    //背景色を黒
    SetBackgroundColor(0, 0, 0);

    //DXライブラリ初期化処理
    if (DxLib_Init() < 0) return -1;


    //文字配列
    char Disp_Char[SIZE][40];           //表示文字列
    char Typing_Char[SIZE][30];         //打つ文字列

    int Typing_Num[50];

    const char mozi3[30] = { 'a','i','u','e','o','k','s','t','n','h','m','y','r','w','\0' };    //正解判定文字列

    //表示させる文字データを読込む
    int FileHandle;
    FileHandle = FileRead_open("./data/01.表示文字.csv");
    for (int i = 0; i < SIZE; i++) {
        FileRead_gets(Disp_Char[i], 50, FileHandle);
    }
    FileRead_close(FileHandle);
    FileRead_close(FileHandle);
    FileHandle = FileRead_open("./data/03.打つ文字.csv");
    for (int i = 0; i < SIZE; i++) {
        FileRead_gets(Typing_Char[i], 50, FileHandle);
    }
    FileRead_close(FileHandle);

    Status status = STATUS_TITLE_INIT;

    int Rand_Num = 0;
    DATEDATA Date;
    int StartTime;

    char String[2];
    char InputChar;

    char mo;
    int i = 0;

    // ESCキーが押されるか、何らかの内部エラーが発生するまでループする
    while (!ProcessMessage() && (CheckHitKey(KEY_INPUT_ESCAPE) == 0)) {
        ClearDrawScreen();
        switch (status) {
            case STATUS_TITLE_INIT: // タイトル画面初期化
                status = STATUS_TITLE;
                // このままタイトル画面の処理も行う (breakなし)
            case STATUS_TITLE: // タイトル画面
                //表示
                DrawString(0, 0, "J1 やさしい ゲームタイピング画面です。", GetColor(255, 255, 255));
                DrawString(0, 20, "Escキー又はBackSpaceを押すとメニュー画面に戻ります。", GetColor(255, 255, 255));
                DrawString(0, 40, "Spaceキーを押すとゲームが開始されます。", GetColor(255, 255, 255));

                //スペースキーが押されるまで
                if (CheckHitKey(KEY_INPUT_SPACE) == 1) {
                    status = STATUS_GAME_INIT;
                }
                break;
            case STATUS_GAME_INIT: // ゲーム初期化
                Rand_Num = GetRand(SIZE);

                //現在時刻の入手
                GetDateTime(&Date);

                //現在経過時間の入手
                StartTime = GetNowCount();

                status = STATUS_GAME;
                // このままゲーム画面の処理も行う (breakなし)
            case STATUS_GAME: // ゲーム画面
                // 入力される文字を随時画面中央に描画します
                String[1] = 0;
                //表示
                SetFontSize(18);
                DrawString(0, 0, "J1 やさしい ゲームタイピング画面です。", GetColor(255, 255, 255));
                DrawFormatString(0, 60, GetColor(255, 255, 255), "残り:%d秒", (60000 - (GetNowCount() - StartTime)) / 1000);
                //最初に表示される黒文字
                SetFontSize(30);
                DrawString(150, 200, Disp_Char[Rand_Num], GetColor(255, 255, 255));
                DrawString(150, 250, Typing_Char[Rand_Num], GetColor(255, 255, 255));
                //InputAnswerに格納されている答えの文字と比較して一致するまで入力させる
                InputChar = GetInputChar(TRUE);
                if (InputChar != 0 && InputChar >= CTRL_CODE_CMP) {
                    String[0] = InputChar;
                    String[1] = '\0';
                    if (String[0] == mozi3[i]) {
                        //正しく打てた文字を描画(赤色に変更します)
                        DrawString(i * 100 + 50, 300, Disp_Char[i], GetColor(255, 0, 0));
                        DrawString(i * 100 + 70, 350, Typing_Char[i], GetColor(255, 0, 0));

                        //次の文字に移るため
                        //i++;
                    }

                }
                //計測開始から60秒が過ぎるまでループ 
                if (GetNowCount() - StartTime > 60000) {
                    status = STATUS_RESULT_INIT;
                }
                break;
            case STATUS_RESULT_INIT: // 結果画面初期化
                status = STATUS_RESULT;
                // このまま結果画面の処理も行う (breakなし)
            case STATUS_RESULT: // 結果画面
                break;
        }
    }

     DxLib_End();    // DXライブラリ使用の終了処理
     return 0;        // ソフトの終了
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
あたっしゅ
記事: 664
登録日時: 13年前
住所: 東京23区
連絡を取る:

Re: タイピングゲーム 入力動作に関して

#4

投稿記事 by あたっしゅ » 1年前

東上☆海美☆「
そもそも、

ファイル "01.表示文字.csv"
ファイル "03.打つ文字.csv"

が、up されていないみみ。
VTuber:
東上☆海美☆(とうじょう・うみみ)
http://atassyu.php.xdomain.jp/vtuber/index.html
レスがついていないものを優先して、レスするみみ。時々、見当外れなレスしみみ。

中の人:
手提鞄あたッしュ、[MrAtassyu] 手提鞄屋魚有店
http://ameblo.jp/mratassyu/
Pixiv: 666303
Windows, Mac, Linux, Haiku, Raspbery Pi, Jetson Nano, 電子ブロック 持ち。

Ken2929
記事: 6
登録日時: 1年前

Re: タイピングゲーム 入力動作に関して

#5

投稿記事 by Ken2929 » 1年前

ありがとうございました、参考にします.

返信

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