2

カードのデッキをシャッフルするプログラムを作成するだけで、RNGがforループの内側にシードされているか外側にシードされているかによって動作が異なります。すなわち。

  for(int i = 0; i < 52; i++)
{
  srand(time(0));  
  Card temp = deck[i];
  int toSwap = rand()%52;
  deck[i] = deck[toSwap];
  deck[toSwap] = temp;
}

出力を与えます

Nine of Hearts
Ace of Clubs
Two of Clubs
Three of Clubs
Four of Clubs

など、しかし

void DeckOfCards::shuffle()
{
  srand(time(0));  
  for(int i = 0; i < 52; i++)
  {
  Card temp = deck[i];
  int toSwap = rand()%52;
  deck[i] = deck[toSwap];
  deck[toSwap] = temp;
  }
  currentCard =0;
}

につながる

Ace of Hearts
Queen of Spades
Four of Hearts
Seven of Clubs
Five of Hearts

(正しい機能)。RNGを再シードするとなぜこれが発生するのか誰もが知っていますか?

4

4 に答える 4

3

time(NULL) は毎秒しか変化しないため、for ループが完了するのに 1 秒以上かからない場合、RNG シードは同じになります。

于 2012-07-18T15:04:52.980 に答える
3

疑似乱数が必要な場合、シードは 1 回だけ必要です。srand を何度も呼び出し、クロック シードが変更される前に実行すると、ランダムではなく同じ値が得られます。最初に一度種をまくだけです。他のプログラム (winamp など) を開いて、よりランダムな値を取得することができます (プログラムを遅くする必要があります;) または、ランダムな反復のために空のループを作成すると、最初のプログラムが修正される可能性があります。ただし、20億のような非常に大きなランダムが必要です(40億未満でなければなりません))

于 2012-07-18T15:03:19.673 に答える
0

代わりにブースト posix 時間を使用できます。

ただし、どの場合でも srand を 2 回だけ呼び出す必要がある場合は、2 つの異なる固定値を使用できます。

または、この関数を使用して時間をミリ秒単位で取得します

 inline long
    getTimeMs ()
    {
      struct timeval start;
      long mtime;

      gettimeofday (&start, NULL);

      mtime = ((start.tv_sec) * 1000 + start.tv_usec / 1000.0) + 0.5;

      return mtime;
    }

よろしく

于 2012-07-18T15:53:29.827 に答える
0

ランダム性が低下するため、ループ内で srand(time(0)) を使用したくないという他の人は完全に正しいですが、同じシードを繰り返し設定しているため、それを覚えておくことをお勧めしますデバッグ用: ケースを「再生」できるようにする必要がある場合は、シードをログファイルに書き出し、シードを明示的に設定できるようにします。そうしないと、乱数を使用したアプリケーションのデバッグがかなり難しくなる可能性があります...

于 2012-07-18T15:44:23.023 に答える