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

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

ただいまの
回答率

90.01%

乱数の重複チェック方法

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 926

こんにちは
前回の質問から間が空いてしまったため再度質問を投稿しました。
ビンゴカード作成の重複チェックについて質問があります。
前回の回答を参考にコードを修正してみたのですが、以下の仕様でカードを作成した場合、乱数の重複チェックを入れるとしたら
number[rnd] = tmp;の直後でしょうか?

また、現在のコードでは重複してしまいますが、代入時のループ順で重複チェックなしでも実現でも重複せずに表示させることは可能でしょうか?
知恵をお借りしたいです。

【仕様】
5x5のビンゴカード
表示する数字は1~75まで
縦一列は1~15の範囲で横5列分
初期化、代入、表示の3つのブロックに分ける
bingo変数の縦列ににランダムで作成した配列を5個入れる

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

#define BINGO_HEIGHT (5)//縦5マス
#define BINGO_WIDTH (5)//横5マス
#define MAX_NUM (15)//ビンゴの数値幅

int main(void)
{
    int bingo[WIDTH][BINGO_HEIGHT];//ビンゴカード
    int number[MAX_NUM];//ビンゴナンバー
    int rnd;//乱数
    int cnt_arr;
    int cnt_col;//縦カウンタ
    int cnt_row;//横カウンタ
    int tmp;

    srand((unsigned)time(NULL));/* 乱数系列の変更 */


    for (cnt_arr = 0; cnt_arr< MAX_NUM; cnt_arr++) {//配列初期化
        number[cnt_arr] = cnt_arr +1;
    }

    //bingo変数への代入
    for (cnt_row = 0; cnt_row < BINGO_WIDTH; cnt_row++) {
        for (cnt_col = 0; cnt_col < BINGO_HEIGHT; cnt_col++) {
            for (cnt_arr = 0; cnt_arr < MAX_NUM; cnt_arr++) {//配列シャッフル
                rnd = rand()%(MAX_NUM);
                tmp = number[cnt_arr];
                number[cnt_arr] = number[rnd];
                number[rnd] = tmp;
            }
        // bingo変数に並び替えた乱数配列の先頭5列を代入
        bingo[cnt_row][cnt_col] = number[cnt_col] + (MAX_NUM*cnt_col);
        }
    }
    //bingo変数の表示
    for (cnt_row = 0; cnt_row <BINGO_WIDTH; cnt_row++) {//ビンゴカードのマスを生成した数値で埋める
        for (cnt_col = 0; cnt_col <BINGO_HEIGHT; cnt_col++) {
            printf("%2d ", bingo[cnt_row][cnt_col] );//出力 
        }
        putchar('\n');//改行
    }
    return 0;
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+2

こんにちは。

う~~ん、物凄く惜しいです。あとちょっとのところまでできてますよ。
シャッフル方式ですので重複チェックは不要ですね。

さて、cnt_colを1つ変える度にシャッフルしてます。5列分なので計5セットのシャッフルで良いはずですが、このせいで25セットシャッフルしてますよ。
また、下記をよ~~~く見なおしてみて下さい。こちらも良くやってしまう小さなミスが1つあります。

        bingo[cnt_row][cnt_col] = number[cnt_col] + (MAX_NUM*cnt_col);

最後に、列と行が混乱していると思います。
最後の表示で、row(行)をBINGO_WIDTHだけ回すって可笑しいですよね?
5行ある時、高さが5行分ですね。幅が5行分ってありえないでしょ?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/01/10 06:38

    Chironianさん、ご指摘ありがとうございます。
    以下のコードで解決することができました。
    ループした時の変数がごちゃごちゃになっていたため本来入れるべき変数を間違えていました。
    bingo[cnt_row][cnt_col] = number[cnt_row] + (MAX_NUM*cnt_col);
    にすることで重複なく表示できました。

    何度も回答いただき本当にありがとうございます!

    キャンセル

  • 2016/01/10 13:43

    う~ん、外しまくっているように思います。
    行と列がますます混乱してないでしょうか?
    cnt_rowは行番号、cnt_colは列番号ですよね?
    cnt_row=0の時先頭行、cnt_row=4の時最後の行、cnt_col=0の時左端列、cnt_col=4の時右端列ですよね?

    手間がかかりますが、1行づつ手でシミレートしてみませんか?
    number[]とbingo[][]に対して、どのような値が設定されるかを手で確認するのです。
    もし、面倒でしたら、IDEでステップ実行しつつ、これらの変数の内容を確認するのもよいと思います。

    たぶん、下記ループのcnt_col=1まで進んだ段階で何が可笑しいか判る筈です。

    > //bingo変数への代入
    > for (cnt_row = 0; cnt_row < BINGO_WIDTH; cnt_row++) {
    > for (cnt_col = 0; cnt_col < BINGO_HEIGHT; cnt_col++) {

    キャンセル

  • 2016/01/10 16:26

    すみません、前回のコードに記載していない変更コードがありました。
    回答通りcnt_rowは行(横)、cnt_colは列(縦)を表しています。
    縦のループに対してランダムの配列を作成した後に横のループを回すように変更しています。
    //bingo変数への代入
    for (cnt_col = 0; cnt_col < BINGO_HEIGHT; cnt_col++) {
    for (cnt_arr = 0; cnt_arr < MAX_NUM; cnt_arr++) {//配列シャッフル
    rnd = rand() % (MAX_NUM);
    tmp = number[cnt_arr];
    number[cnt_arr] = number[rnd];
    number[rnd] = tmp;
    }
    for (cnt_row = 0; cnt_row < BINGO_WIDTH; cnt_row++) {
    // bingo変数に並び替えた乱数配列の先頭5列を代入
    bingo[cnt_row][cnt_col] = number[cnt_row] + (MAX_NUM*cnt_col);
    }
    }

    キャンセル

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

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