質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.61%

タイピングゲームの作成、乱数について

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 4,556

yowappu

score 13

前提・実現したいこと

Cでタイピングゲームのような物を作っているのですが、今のコードのままだとランダムに表示させた問題を正解したときに再度同じ問題が出てしまいます
既に使用した配列の中身を排除していく方法がわからず苦戦しています
どうすればいいでしょうか?

発生している問題・エラーメッセージ

同じ問題が出てしまう

該当のソースコード

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main()
{
    //単語設定
    char *word[] = {"banana","rinngo",......};//例です
    char typing[256];

    int count;    //ループ用変数
    clock_t start,end;

    srand((unsigned)time(NULL));    //乱数発生

    for(count = 0; count < 10; count++){    //ループ処理
    start = clock();    //時間計測スタート

        int wordchange = rand () % 20;

        while(*word != typing){    //比較処理
            puts(*(word + wordchange));
            gets(typing);

            if(strcmp(*(word + wordchange),typing) == 0){
                puts("\n\"right!\"\n");    //正解
                break;
            }
            else{
                puts("\n\"Nooooo!!!!\"\n");    //不正解
            }
        }
    }
    end = clock();    //時間計測終了
    printf("あなたは %d秒 でした。\n",end/CLOCKS_PER_SEC);    //結果表示、CLOCKS_PER_SECで変換



    return 0;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

調べればやり方はいくつか出てくるのでしょうけど、考え方のひとつを紹介します。
まずword配列参照用の配列(idxとしておきます)を用意します。
word配列の要素数が20個なら同じく20個です。
初期値は、0~19です(idx[0]=0,idx[1]=1,...)
乱数の範囲は0~19で、最大値を1問ごとに減らしていきます。
word配列の参照は、idx配列を介して行います。
int wordchange = rand () % randmax;
word[idx[wordchange]]
1問終わるごとに、idx配列の対象要素を削除し後ろを詰めます。
例えば、乱数の結果、2だったとすると、idx配列を次のように組み直します。
idx[0]=0
idx[1]=1
idx[2]=3
idx[3]=4
...

それからstart = clock()はfor文の外に出さないと1問ごとの時間になってしまいますよ。

修正版コード

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main()
{
    //単語設定
    char *word[] = {"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20"};
    char typing[256];
    clock_t start,end;
    char idx[20];
    int i;
    int randmax = 20;
    int wordchange;

    // idx配列の初期化
    for(i = 0; i < 20; i++) idx[i] = i;

    srand((unsigned)time(NULL));    //乱数発生

    int count;    //ループ用変数

    //時間計測スタート
    start = clock();
    for(count = 0; count < 10; count++){    //ループ処理
        wordchange = rand () % randmax;

        while(*word != typing){    //比較処理
            puts(word[idx[wordchange]]);
            gets(typing);

            if(strcmp(word[idx[wordchange]],typing) == 0){
                puts("\n\"right!\"\n");    //正解
                break;
            }
            else{
                puts("\n\"Nooooo!!!!\"\n");    //不正解
            }
        }
        // idx配列を詰める
        for(i = wordchange; i < 20; i++) idx[i] = idx[i + 1];
        randmax--;
    }
    end = clock();    //時間計測終了
    printf("あなたは %d秒 でした。\n",end/CLOCKS_PER_SEC);    //結果表示、CLOCKS_PER_SECで秒に変換

    return 0;
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/09/12 15:27

    コードありがとうございます。
    問題点を修正したコードを本文の方に貼っておきました。
    参考にしてください。
    直した箇所は以下です。
    ・idx配列の初期化をループ化
    ・RAND_MAXを変数化
    ・変数wordchangeを関数先頭で宣言(ループの外で使うため)
    ・idx配列を詰める処理を追加
    ・randmaxをデクリメントする処理を追加
    ・計測スタートをループの外に移動

    キャンセル

  • 2016/09/12 15:29

    それから先ほどのコードはとりあえず動く状態にしたので、本来なら20などハードコーディングせずに、マクロで定義したり、配列の要素数から求めるべきです。
    今のコードの理解ができたら、そういったところも見直してみてください。

    キャンセル

  • 2016/09/12 15:32

    丁寧な回答たいへんありがとうございます

    教えていただいたのにも関わらず配列を詰める処理などを考えていませんでした・・
    今回教えていただいたことを参考にしもっと勉強していきたいと思います。
    ありがとうございました

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る