- ベストアンサー
乱数について教えてください!
私はいまC言語で,1~10までの数字をランダムに10個発生させるプログラムを作っています. 単にランダムに発生させることはできるのですが,そうではなくて,10個の中に同じ数字が出てこないようにしたいのです. その方法についてどなたかご存知の方がおられましたら,ご教授お願い致します.
- みんなの回答 (9)
- 専門家の回答
質問者が選んだベストアンサー
フラグを立てる方法でも、 発生する乱数を、最初は1~10、次は1~9…としておいて、 「使っていない数字の何番目」と解釈するようにすると 無駄な乱数の生成を抑えることができます。 今書きました。使えれば使ってください。 いちおう動きますが詳しいテストはしてません。 /*0~9の乱数を作る*/ #include <stdio.h> #include <stdlib.h> #include <time.h> #define NUM 10 int random_number(int n); int main(void){ int output[NUM]; int flag[NUM]; int i, j, counter; int x; /*乱数を起動時ごとに違う値にする初期化*/ srand(time(NULL)); /*フラグ初期化*/ for(i = 0; i < NUM; i++){ flag[i] = 0; } /*乱数発生*/ for(i = 0; i < NUM; i++){ x = random_number(NUM - i); /*まだ使ってない数のx番目を探す*/ for(j = 0; j < NUM; j++){ if(flag[j] == 0)x--; if(x < 0){ flag[j] = 1; output[i] = j; break; } } } for(i = 0; i < NUM; i++){ printf("%d ", output[i]); printf("\n"); } return 0; } /*0からn-1までの乱数を返す関数*/ int random_number(int n){ return rand() / (RAND_MAX / n + 1); }
その他の回答 (8)
- JaritenCat
- ベストアンサー率37% (122/322)
1~10を並べておいてシャッフルする方法が簡単で無駄がないと思います。 #include <stdio.h> #include <stdlib.h> int main(void) { int list[10]={1,2,3,4,5,6,7,8,9,10}; int i,j,tmp; for (i=0;i<10;i++) { j=rand()%10; /* 0~9の擬似乱数 */ tmp=list[i];list[i]=list[j];list[j]=tmp; /* i番目とj番目を入れ替え */ } for (i=0;i<10;i++) { printf("%2d ",list[i]); } return 0; }
お礼
解答してくださった皆様にまとめてお礼申し上げます. 皆様のおかげで問題を解決することができました. 本当にありがとうございました. 今後もまたよろしくお願い申し上げます.
- leaz024
- ベストアンサー率75% (398/526)
そのような場合は1~10を順にセットした配列を用意し、ランダムにシャッフルするという方法がシンプルでしょう。シャッフルには単純選択ソートを応用したアルゴリズムを用いると、乱数生成の無駄がありません。 #include <stdio.h> #include <stdlib.h> #include <time.h> #define CNT 10 void shuffle(int *, int); int main(void) { int array[CNT], i, r, tmp; /* 乱数系列初期化 */ srand(time(NULL)); /* 配列に1~CNTをセット */ for (i = 0; i < CNT; i++) array[i] = i + 1; /* シャッフル */ shuffle(array, CNT); /* 確認 */ for (i = 0; i < CNT; i++) printf("%2d\n", array[i]); return 0; } void shuffle(int *list, int n) { int r, tmp; while (--n) { r = (int)(rand() / (RAND_MAX + 1.0) * (n + 1)); tmp=list[n], list[n]=list[r], list[r]=tmp; } } ※インデントは全角空白なので、コピーする時はタブなどに置換して下さい。
お礼
解答してくださった皆様にまとめてお礼申し上げます. 皆様のおかげで問題を解決することができました. 本当にありがとうございました. 今後もまたよろしくお願い申し上げます.
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
/* 1~10の数を適当に作る */ #include <stdio.h> #include <stdlib.h> #include <sys/timeb.h> void main(void){ int r,c,i; int list[10]={ 0,0,0,0,0,0,0,0,0,0 }; int result[10]; struct timeb tm; ftime(&tm); srand(tm.millitm); c=0; for(i=0;i<10;i++){ if(list[i]==0){ if(list[r=rand()%10]++==0) result[c++]=r+1; i--; } } for(i=0;i<10;i++) printf("%2d\n",result[i]); }
お礼
解答してくださった皆様にまとめてお礼申し上げます. 皆様のおかげで問題を解決することができました. 本当にありがとうございました. 今後もまたよろしくお願い申し上げます.
- GoF
- ベストアンサー率37% (34/91)
1) 1~10を代入した配列を用意する 2) 乱数で0~9を発生させて、取り出す要素番号を取得 3) 配列の中身を別の配列にPUSH 4) 該当要素を配列から抹消 5) 1)~4) を 10回繰り返す 但し 2)の最大値は-1する 10個程度なら、配列でなくて'0123456789'の文字操作で置換可能
お礼
解答してくださった皆様にまとめてお礼申し上げます. 皆様のおかげで問題を解決することができました. 本当にありがとうございました. 今後もまたよろしくお願い申し上げます.
- ymmasayan
- ベストアンサー率30% (2593/8599)
配列に1から10の数字を入れておきます。 1から9の乱数を引いてその順番の数値と10番目の数値を交換します。 これを100回くらい適当に繰り返します。
お礼
解答してくださった皆様にまとめてお礼申し上げます. 皆様のおかげで問題を解決することができました. 本当にありがとうございました. 今後もまたよろしくお願い申し上げます.
- syosyosyo
- ベストアンサー率33% (32/95)
10個固定でいいのであれば、フラグを10個用意して、一度発生した数字はフラグを立ててはどうですか? フラグが立っている場合は、フラグの立ってない数字が出るまで、繰り返し乱数を発生させるわけです。 10個固定ということで、レスポンスやプログラムの美しさは考慮してませんが。
お礼
解答してくださった皆様にまとめてお礼申し上げます. 皆様のおかげで問題を解決することができました. 本当にありがとうございました. 今後もまたよろしくお願い申し上げます.
- micchan32
- ベストアンサー率22% (240/1054)
1.ランダムな数字を発生 2.その数字を記録 3.もし過去に同じ数字があったら1に戻る 4.数字を記録 5.何回目か記録 6.10回なら終了 7.1に戻る
お礼
解答してくださった皆様にまとめてお礼申し上げます. 皆様のおかげで問題を解決することができました. 本当にありがとうございました. 今後もまたよろしくお願い申し上げます.
- mcq
- ベストアンサー率48% (45/93)
方法は色々ありますが、一番簡単なのは 「今まで出てきた数字を配列に保存しておいて、まだ出ていない数字が出るまで乱数を発生し続ける」 という方法ではないでしょうか?
お礼
解答してくださった皆様にまとめてお礼申し上げます. 皆様のおかげで問題を解決することができました. 本当にありがとうございました. 今後もまたよろしくお願い申し上げます.
お礼
解答してくださった皆様にまとめてお礼申し上げます. 皆様のおかげで問題を解決することができました. 本当にありがとうございました. 今後もまたよろしくお願い申し上げます.