
C#で複重しない乱数
とにかく自分の書いたプログラムの一部分を見てください
Bitmap my1 = new Bitmap(GetType(), rand.Next(1,52) + ".png");
Bitmap my2 = new Bitmap(GetType(), rand.Next(1,52) + ".png");
Bitmap my3 = new Bitmap(GetType(), rand.Next(1,52) + ".png");
Bitmap my4 = new Bitmap(GetType(), rand.Next(1,52) + ".png");
Bitmap my5 = new Bitmap(GetType(), rand.Next(1,52) + ".png");
Bitmap my6 = new Bitmap(GetType(), rand.Next(1,52) + ".png");
Bitmap my7 = new Bitmap(GetType(), rand.Next(1,52) + ".png");
Bitmap my8 = new Bitmap(GetType(), rand.Next(1,52) + ".png");
Bitmap my9 = new Bitmap(GetType(), rand.Next(1,52) + ".png");
Bitmap my10 = new Bitmap(GetType(), rand.Next(1,52) + ".png");
Bitmap my11 = new Bitmap(GetType(), rand.Next(1,52) + ".png");
Bitmap my12 = new Bitmap(GetType(), rand.Next(1,52) + ".png");
Bitmap my13 = new Bitmap(GetType(), rand.Next(1,52) + ".png");
Bitmap my14 = new Bitmap(GetType(), rand.Next(1,52) + ".png");
こんなかんじで、なんかプログラムが回りくどかったり下手くそだったりするのは触れないでくださいww
1~52の乱数を発生させてるのですが、コレが同じ数字が出て欲しくないんですけど
やり方が分かりません^^;
どなたか教えてくれませんか
No.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回を超えると空きの数値が無いので帰ってこなくなります。
つまり、それ以上はランダムは出来ないってことですか?
プログラム試しました
すごいです。重複しませんでした
難しいですね
とりあえずこれを使ってプログラムを作っていきたいと思います
ありがとうございました
No.5
- 回答日時:
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枚カードが配られるようなプログラムを作っています
考え方はわかるのですが・・・
なるほど・・・少しづつ解読していきます
No.4
- 回答日時:
> public int rand()
> の部分でrandにエラーが出てきてしまいます
> randの定義をすでに含んでいますって感じです
System.Randomのオブジェクトとクラスの関数(メソッド)名がダブってましたね。
どちらを変えても同じですけど、関数名の方を適当に変えてください。
public int urand()
とか……(関数を呼び出してるところも)
だいぶ理解してきました
でも結局うまくいきませんでした・・・
すいませんこんなに詳しく描いてもらったのに
今後この技術も活用させてもらいたいと思います
ありがとうございました
No.3
- 回答日時:
> voidがダメみたいです無効なパラメーター型です。
っていわれますC#だと引数のない場合は何も書かないみたいですね。
(CとかC++の方が慣れてるから、ついvoidを書いてしまいましたが)
public int rand()
で良いと思います。
No.2
- 回答日時:
#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の定義をすでに含んでいますって感じです
お手数かけてすいません
No.1
- 回答日時:
乱数はランダムに値を生成しますが、同じ値を生成しないという機能はありません。
特に上下限値を指定した場合は値の取りうる範囲が狭いので、重複した値が出る確率は高くなります。重複した値を排除したいのであれば、自分で管理するしないでしょう。
例えば
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");
というのもひとつの方法です。
この回答への補足
public int rand(void)
すいません、この部分でエラーが出てしまいます
いろいろ試してみたのですが、分からないです・・・^^;
voidがダメみたいです無効なパラメーター型です。っていわれます
教えてもらってるのにすいません・・・
すごいです・・・
えーっとクラスを作ってこのプログラムを入力すればいいのでしょうか・・・
ごめんなさい、C#はまだ勉強中でいまいち理解できてなくて
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
c言語プログラミングについて f...
-
クリックされた地点が2点の線分...
-
openCVの画像処理について
-
C++ bmp 透過処理
-
intとlongは同じ?
-
C++デバックエラーについて詳し...
-
C++ Debug Errorについて教えて
-
再起呼び出しの回数をカウント...
-
C言語プログラミング 漸化式に...
-
「Aに対するBの割合」と「Aに対...
-
2÷3などの余りについて
-
信頼区間の1.96や1.65ってどこ...
-
Aの値からBの値を除するとは??
-
C言語での引数の省略方法
-
20'(角度)の計算がわかりま...
-
C言語のfor文です。 繰り返しの...
-
long型の定数の末尾にLを付ける...
-
マイナスからプラスへ転じた時...
-
Enterキーを押されたら次の処理...
-
ある商品のロス率を5%見込み、...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
2の補数を計算するプログラム
-
【C#】SQL文の中に変数を埋め込...
-
再起呼び出しの回数をカウント...
-
C言語のプログラムについて(...
-
C言語で%を使わない余りの出し方
-
3のつく数と3の倍数を表示 C言語
-
分数の足し算をさせるプログラ...
-
intとlongは同じ?
-
C++で表を作成したいのです ...
-
c言語プログラミングについて f...
-
再帰処理をループ処理に変換
-
argvのNULLチェック
-
コマンドプロンプトのウィンド...
-
ヌメロンのプログラム
-
条件が多い場合
-
C言語でDOS画面のプログラム(...
-
プログラミングに関して
-
ヒストグラム均等化処理プログラム
-
複数の共有メモリの作成
-
OpenGLの惑星プログラム
おすすめ情報