1

rand関数とsrand関数を使用して2つの独立したランダムシーケンスを生成するのに問題があります。詳細は以下の通りです、どんな助けでも大歓迎です。

私はiPhone用のパズルゲームに取り組んでおり、通常、乱数の生成にはarc4関数を使用します。ただし、マルチプレイヤーモードの場合、ゲーム全体で両方のプレイヤーに同じピースを持たせたいので、それを制御できる唯一の方法は、2つの繰り返し可能なランダムシーケンスを使用することです。その後、シードを他のデバイスに送信すると、ゲームは同じになります。ただし、randとsrandを使用して他のシードに切り替えようとすると、シーケンスは最初から開始され、シードで生成された2つの独立したシーケンスをどういうわけか初期化する必要があります。

ご回答ありがとうございます

4

6 に答える 6

2

暗号的に悪いPRNGrand()は、前の結果を特定の数学的手順にフィードバックすることによって動作します。

中断したところからシーケンスを続行するには、最後に生成された番号を保存し、それをシードとして使用するだけです。

srand(time(0));
int player1_rand_num = rand();
NSLog(@"Player 1: %d, %d, %d", rand(), rand(), rand());
srand(7);
int player2_rand_num = rand();
NSLog(@"Player 2: %d, %d, %d", rand(), rand(), rand());

// Re-seed Player 1 sequence
srand(player1_rand_num);
// Displays the same "random" numbers as the first NSLog
NSLog(@"Player 1 again: %ld, %ld, %ld", rand(), rand(), rand());
// and so on...

このrandom()関数は、より適切な乱数を生成し、別個の関数のペアを備えておりinitstate()setstate()ジェネレーターの状態を提供します。状態を保存してに渡すと、setstate()中断したところからシーケンスを再開できます。詳細をご案内しますman 3 random

于 2012-02-18T17:53:32.693 に答える
1

提案をありがとう、これは私がすべてを実装した方法です。2つのインスタンス変数(seed1とseed2)を使用してシングルトンクラスを作成しました。最初のジェネレーターから数値を取得したいときはいつでも、generator2メソッドと同じメソッドgenerator1を使用します。seed1 / 2は毎回新しく生成された番号に即座に設定されるので、中断したところから続行できます。結論として、JoshCaswellは私に必要なすべての情報を提供してくれました。このようなものが必要な場合は、コードを確認してください。オブジェクトはシード1と1で初期化されますが、ゲーム中に、両方のデバイスが共有する他のいくつかの番号に置き換えられます。

@implementation RandomNumberGenerator

@synthesize seed1,seed2;

static RandomNumberGenerator *sharedGenerator = nil;

+(RandomNumberGenerator *) sharedInstance
{
if(!sharedGenerator) {
    sharedGenerator = [[RandomNumberGenerator alloc] initWithSeed1:1 andSeed2:1];
}

return sharedGenerator;
}

-(id) initWithSeed1:(int) seedOne andSeed2:(int) seedTwo{
self = [super init];
if (self)
{
    seed1 = seedOne;
    seed2 = seedTwo;
}
return self;
}

-(int) generator1{
srand(seed1);
int j = rand();
seed1 = j;
return abs(j);

}

-(int) generator2 {
srand(seed2);
int k = rand();
seed2 = k;
return abs(k);
}

-(int) giveRandom {
//return abs(arc4random());
return abs(arc4random());
}


@end
于 2012-02-20T03:35:56.503 に答える
1

まず、他の人がすでに指摘しているようrandom()に、の代わりにを使用する必要がありrand()ます。第二に、あなたのシングルトンアプローチはあなたのために働くかもしれませんが、あなたはあなたの問題をより簡単に解決し、そして私見をより優雅に使うことができますsetstate(3)。2つの乱数状態を切り替える方法の例については、setstate(3)を使用しても期待される一連の乱数が生成されないを参照してください。

于 2014-02-26T02:26:07.153 に答える
0

Did you seed your random number generator?

srand( myIdenticalSeedValueForBothPartners );

See this question or here [C++ reference].

In case you don't need to call rand() many thousand times:

int nthRandBasedOnSeed( int seed, int count ) {

   srand( seed );

   int result;
   while( 0 < count-- ) {

     result = rand();

   }

   return result;

}
于 2012-02-18T17:36:58.597 に答える
0

または、シードとともに「カウント」を送信することを検討することもできます。このカウントは、シードされたシリーズのどこにいるかを示すだけであり、そのシードで乱数を生成するたびに増加します。このアプローチにより、任意のランダムジェネレーターを柔軟に使用でき、通信を最小限に抑えることができます。

int playerSeed = 12345;
int playerRndCount = 0;

int generateRandomNumber() {
    playerRndCount++;
    return rand();
}

void synchSeed(seed, count) {
    srand(seed);
    for (int i=0;  i<count;  i++)
        generateRandumNumber();
}
于 2012-02-19T09:31:11.727 に答える
-1

一部の乱数ジェネレータライブラリでは、ジェネレータの状態を保存できます。このようにして、後で復元し、すでに進行中のシーケンスを続行できます。私が知っているものはRandomLibと呼ばれ、SourceForgeで見つけることができます。

もう1つのオプションは、シードを保存し、シード後にジェネレーターから値を取得した回数をカウントすることです。後で続行する場合は、元のシードを再シードして、同じ量を取り除きます。これはおそらく最善の方法ではありませんが、多くのことをしなくてもうまくいくはずです。

于 2012-02-18T17:59:31.047 に答える