2010-12-03 7 views
4

リストのランダム化には多くの問題がありました。私はリストをシャッフルしたい200の要素のリストについて話しています。誤解しないで、私は例をたくさん読んで、そして一見にかなりいいものがあり、このような:C#ランダムコード - そのほとんどは間違っていますか?

Randomize a List<T>

しかし、私の経験では、少なくとも高速なマシンで、これがあります基本的に価値がない。シャッフルは非常に速く動作し、Random.NEXT()への2回の呼び出しの間にMS遅延がないため、ほとんどランダムではない動作になります。

私はスーパーセキュアなものについて話しているわけではなく、基本的なゲームはランダムです。私は1 MSの遅延を追加することができますが、これは単にリストをランダム化するために200 MSを "無駄にする"ことを意味します。

は今、私はこのアプローチを見つけた:http://www.codinghorror.com/blog/2007/12/shuffling.html

それはソートするためにGUIDを使用して、良さそうに見えます。しかし、彼らは同じように作成されていませんか?ノッチそれをステップアップすることができます0の間、私は1000個の数字を作成したいと仮定することができます - このコードは、基本的に役に立たない5.:

 var resultA = new List<int>(); 
     for (int i = 0; i < 1000; i++) 
     { 
      resultA.Add(new Random().Next(5)); 
     } 


     var resultB = new List<int>(); 
     for (int i = 0; i < 1000; i++) 
     { 
      resultB.Add(new Random().Next(5)); 
      Thread.Sleep(1); 
     } 

Aがまったく動作しない、少なくともWindowsの携帯電話に私の環境イムありません、 7. Bは大丈夫ですが、それはまた愚かです秒を要します。任意のコメントや思考、整数のランダムなリストを作成することは難しくありません:

+0

ああ、私は本当に今の自分自身を憎む[OK]を:-)、それを説明している...まあそこが作成された新しいランダム(それぞれの質問を使用する意味があったいくつかの問題があったが、それはアイテムを配置すべきです1-4で、問題は全体を世話しました)しかし、彼らは速くするために作成されました.Ok、とにかく感謝、私のばかな間違いを持っ​​ています! –

+0

あなたが参照した質問のシャッフル拡張を使用するか、Jon Skeetの実装を見つけることができるかどうかを確認するには、別の質問があります。同じRNGでNext()を連続して呼び出すと、通常は異なる値が返されます(ただし、定期的に重複が発生する可能性があるため「ランダム」です)。 – tvanfosson

+0

ええ、質問では、ランダムジェネレータを親オブジェクト(ゲーム)に移動するだけで問題はありません。しかし、それでも、あなたはこの愚かな間違いをどれくらいの間検索することができて面白いのですか?そして、私は "乱数"がそれほど難しくないと確信していました。 –

答えて

22

Randomの新しいインスタンスを初期化しないでください。ただ1つを作成し、それを絶えず参照してください。あなたが繰り返し同じ「タイムスタンプ」内Randomの新しいインスタンスを作成することを正しい

var random = new Random(); 
var resultA = new List<int>(); 
for (int i = 0; i < 1000; i++) 
{ 
    resultA.Add(random.Next(5)); 
} 

は同じシードになります。無作為のインスタンスで.Nextを呼び出すと、次の番号が(おそらく)異なるように、シードが「進められます」。これはまた、the documentation on Randomで覆われている

...クロックは有限の解像度を持っているので、近くに連続して異なるランダムなオブジェクトを作成するために、パラメータなしのコンストラクタを使用して、乱数の同一の配列を生成乱数ジェネレータを作成します。

...

この問題は、複数のものではなく、単一のランダムなオブジェクトを作成することによって回避することができます。

+0

質問はMarkとBronumskiによってここでかなり扱われているので、これを追加情報として追加します。擬似乱数ジェネレータを数学的シーケンスと考えてください。それをインスタンス化すると、それはシードされ、後続の呼び出しはシーケンスから疑似乱数を生成します。彼らは実際には上記のシーケンスから返された数字だけであるときにランダムであるという外観しか持たないので、「擬似乱数」と呼ばれます。擬似乱数ジェネレータは、ランダムに見えるように互いに評価されることがあります。 –

6

ランダムの同じインスタンスを保持する必要があります。

var random = new Random(); 

    var resultA = new List<int>(); 
    for (int i = 0; i < 1000; i++) 
    { 
     resultA.Add(random.Next(5)); 
    } 


    var resultB = new List<int>(); 
    for (int i = 0; i < 1000; i++) 
    { 
     resultB.Add(random.Next(5)); 
     Thread.Sleep(1); 
    } 

これは、ランダムが初期化されると、システムクロックを使用して特定の時刻を取得するためです。あなたが次回に電話をするとき、時間の差を使って次の番号を得ることができます。ランダムオブジェクトを初期化し続けると、ほとんどの場合同じ数の数字が得られます。

4

シャフリングは非常に速く動作し、Random.NEXT()の2回の呼び出しの間にMS遅延がないため、ほとんどランダムではありません。

Random.Nextへの2回のコールの間にms遅延が必要になると思いますか?

あなたのBog標準乱数生成器は、初期シード(システムクロックなど)をいくつかとり、そのシードに対して何らかのアルゴリズムを繰り返し実行して、ランダムに見える数列を生成します。これらのアルゴリズムのほとんどは、シード以外の入力としてクロックを使用しないため、2回の連続した呼び出しがどれだけ速く実行されるかは関係ありません。

コードが失敗するのは、各繰り返しで新しい乱数ジェネレータをインスタンス化し続けるためです。これは時計があなたを殺すことができるところです。なぜなら、あなたは同じ種の種を二度使い続けるからです。 Random.Nextを同じ乱数ジェネレータで連続して呼び出すことはありません。すべての反復で新しい乱数ジェネレーターでRandom.Nextを呼び出しています。これらの乱数ジェネレーターは、システムクロックでシードしているため、同じ値でシードされることがあります。

乱数ジェネレータのインスタンス化をループ外に移動します。

var resultA = new List<int>(); 
Random rg = new Random(); 
for (int i = 0; i < 1000; i++) { 
    resultA.Add(rg.Next(5)); 
} 
+0

彼は彼のコードで新しいランドスムを作り続けているからだ。 –

+5

@abelenky:私の答えを読んでいないというあなたのコメントを-1つけることができたらどうなるだろう。 – jason

+0

あなたはノイズ/攻撃的/スパムとしてフラグを付けることができます – KevinDTimm

関連する問題