- ベストアンサー
C#で複重しない乱数を生成する方法
- C#で1~52の乱数を発生させるプログラムがありますが、同じ数字が出ないようにする方法を教えてください。
- C#で複重しない乱数を生成する方法について教えてください。
- C#で乱数を発生させるプログラムを作成していますが、同じ数字が出ないようにする方法がわかりません。教えてください。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
動かしてみて動作確認をとってみました。 これで動くと思います。 class UniqueRandom { private int rand_max; private int rand_min; private int rand_range; bool[] check; System.Random rand; private int last_num; public UniqueRandom(int imin, int imax) { rand_max = imax; rand_min = imin; rand_range = imax - imin + 1; check = new bool[rand_range]; for (int i = 0; i < rand_range; i++) { check[i] = false; } rand = new System.Random(); last_num = 0; } #if false public int urand() { int num; do { num = rand.Next(rand_min, rand_max); } while (check[num - rand_min]); check[num - rand_min] = true; return(num); } #else public int urand() { int i, j; int num = rand.Next(rand_min, rand_max); for (i = last_num + 1, j = rand_min; j <= rand_max; i++) { if (i >= rand_range) { i = 0; } if (!check[i]) { if (j == num) break; j++; } } check[i] = true; last_num = i; return(i + rand_min); } #endif } 乱数の取り方は // 乱数生成用のオブジェクト UniqueRandom u_rand = new UniqueRandom(1, 52); // num に 1~52のどれかをユニークに取り込み int num = u_rand.urand(); 当然ながら、52回を超えると空きの数値が無いので帰ってこなくなります。
その他の回答 (5)
- D-Matsu
- ベストアンサー率45% (1080/2394)
52という数字で重複禁止というところからするとトランプの山でも作りたいのでしょうか。 発想の方向を変えて、「1~52の数値を持つ配列をシャッフルし、頭から順次抜き出す」という手法を紹介しておきます。 #たぶんこのままクラスに突っ込んでも動作するんじゃないかな? #シャッフル部分は実装してませんので注意 配列と現在位置: int numbers[52]; int current; シャッフルするルーチン: // num = シャッフル回数 void shuffle(int num) { int i; for(i = 0; i < 52; i ++) { // 配列の初期化 numbers[i] = i + 1; } // 配列をシャッフル for(i = 0; i < num; i ++) { // 適当なシャッフルルーチン // rand二回の実施結果で一枚ずつ入れ替える、というのがとりあえずは楽か } // 参照位置を頭にする current = 0; } // 配列を先頭から順次取っていく // 取れなくなった(=モノがなくなった)ら0を返す int get() { if(current < 52) return numbers[current++]; return 0; }
補足
そうですねトランプです 大富豪を作ろうと思っているのですが全然進まないので 基本的なことから作っていこうと思いまして 手札にとりあえず14枚カードが配られるようなプログラムを作っています 考え方はわかるのですが・・・ なるほど・・・少しづつ解読していきます
- magicalpass
- ベストアンサー率58% (378/648)
> public int rand() > の部分でrandにエラーが出てきてしまいます > randの定義をすでに含んでいますって感じです System.Randomのオブジェクトとクラスの関数(メソッド)名がダブってましたね。 どちらを変えても同じですけど、関数名の方を適当に変えてください。 public int urand() とか……(関数を呼び出してるところも)
お礼
だいぶ理解してきました でも結局うまくいきませんでした・・・ すいませんこんなに詳しく描いてもらったのに 今後この技術も活用させてもらいたいと思います ありがとうございました
- magicalpass
- ベストアンサー率58% (378/648)
> voidがダメみたいです無効なパラメーター型です。っていわれます C#だと引数のない場合は何も書かないみたいですね。 (CとかC++の方が慣れてるから、ついvoidを書いてしまいましたが) public int rand() で良いと思います。
- magicalpass
- ベストアンサー率58% (378/648)
#1 の補足です。 check[num]とあるのはcheck[num - rand_min]に置き換えてください。 下記の例ではテーブルに出た乱数毎にフラグを立てて、その値にフラグが立ってるかどうかの判断を行っていますが、この場合、値の範囲に対して乱を使う回数が少ない場合は良いのですが、テーブルがフラグで埋まってくると新しい値を取り出すのに時間がかかってきます。 したがって、範囲内の値をある程度多く使う場合は、乱数を取り出した値を直接テーブルのインデックスにして判断するのではなく、取り出した乱数でテーブルのフラグの立ってない部分を順次探していくような形にした方が効率的になります。 例えば、下記のUniqueRandomクラスを変更するなら // クラス変数の追加 private int last_num; // コンストラクタの追加 last_num = 0; // 関数本体(置き換え) public int rand() { int i, j; int num = rand.Next(rand_min, rand_max); for (i = last_num + 1, j = rand_min; j <= rand_max; i++) { if (i >= rand_range) { i = 0; } if (!check[i]) { if (j == num) break; j++; } } check[i] = true; last_num = i; return(j); }
補足
こんなに早く、詳しく返答ありがとうございます 少しづつですが部分的に理解ができてきました public int rand() の部分でrandにエラーが出てきてしまいます randの定義をすでに含んでいますって感じです お手数かけてすいません
- magicalpass
- ベストアンサー率58% (378/648)
乱数はランダムに値を生成しますが、同じ値を生成しないという機能はありません。特に上下限値を指定した場合は値の取りうる範囲が狭いので、重複した値が出る確率は高くなります。 重複した値を排除したいのであれば、自分で管理するしないでしょう。 例えば class UniqueRandom { private int rand_max; private int rand_min; private int rand_range; bool[] check; System.Random rand; UniqueRandom(int min, int max) { rand_max = max; rand_min = min; rand_range = max - min + 1; check = new bool[rand_range]; for (i = 0; i < rand_range; i++) check[i] = false; rand = new System.Random(); } public int rand(void) { int num; do { num = rand.Next(rand_min, rand_max); } while (check[num]); check[num] = true; return(num); } } というようなユニーク値を返す乱数クラスを作って UniqueRandom u_rand = new UniqueRandom(1,52); Bitmap my1 = new Bitmap(GetType(), u_rand.rand() + ".png"); というのもひとつの方法です。
お礼
すごいです・・・ えーっとクラスを作ってこのプログラムを入力すればいいのでしょうか・・・ ごめんなさい、C#はまだ勉強中でいまいち理解できてなくて
補足
public int rand(void) すいません、この部分でエラーが出てしまいます いろいろ試してみたのですが、分からないです・・・^^; voidがダメみたいです無効なパラメーター型です。っていわれます 教えてもらってるのにすいません・・・
お礼
つまり、それ以上はランダムは出来ないってことですか? プログラム試しました すごいです。重複しませんでした 難しいですね とりあえずこれを使ってプログラムを作っていきたいと思います ありがとうございました