使用setstate(3)不会产生预期的随机数序列

对于多人游戏,我需要在所有参与设备上生成相同的随机数序列。 显然,这是通过在所有设备上使用相同的种子来实现的。 当在所有设备上产生相同序列的例程之外调用random()时会出现问题。 因此,在这个例程中,我尝试使用setstate来保存状态数组。 据我所知, man random(3) ,在此例程之外调用random()不应该改变序列。

但是,以下代码不会为Run 1和2生成相同的输出:

 #include  #include  #include  int main(int argc, const char * argv[]) { char state[256]; printf("Run 1 : "); initstate(123, state, 256); for (int i=1; i < 10; i++) { printf("%ld ", random()); } printf("\nRun 2 : "); initstate(123, state, 256); for (int i=1; i < 10; i++) { setstate(state); // load preserved state printf("%ld ", random()); *state = *setstate(state); // preserve state random(); // this simulates a call to random() from outside } printf("\n"); return 0; } Run 1 : 1597493280 1407130876 1753502901 1965067074 377602131 83146350 274392949 1718024305 1016176754 Run 2 : 1597493280 537479855 1611694138 941096776 83164437 1459338036 1256894804 1618690717 1091902527 Program ended with exit code: 0 

有谁知道为什么? 或者可能有另一种方法可以达到预期的效果?

记录:使用Xcode 5在OS X和iOS上运行。

编辑在Arkku和minitech的帮助下,以下更改使Run 2的输出与Run 1相同:

  printf("\nRun 2 : "); char otherstate[256]; initstate(123, state, 256); for (int i=1; i < 10; i++) { // preserve whatever state is currently active // and set the current state to "my" state memcpy(otherstate, setstate(state), 256); printf("%ld ", random()); // switch back to the other state memcpy(state, setstate(otherstate), 256); // now this call does not affect the sequence that get's printf'd random(); } printf("\n"); 

在第二个循环中,您可以调用random()而不打印该值。 而且, setstate线是没用的; 每次使用相同的数组( state ),因此状态将不断变化。 这两个序列完全相同:

 for (int i = 1; i <= 2; ++i) { printf("\nRun %d: ", i); initstate(123, state, sizeof(state)); for (int i=1; i < 10; i++) { printf("%ld ", random()); } } 

如果您需要在生成一些随机数后保存状态,然后再返回到同一状态,则必须在不同的状态数组之间切换,例如:

 char state[256], state2[256]; initstate(123, state, sizeof(state)); char *saved = initstate(123, state2, sizeof(state2)); for (int i=1; i < 10; i++) { saved = setstate(saved); printf("%ld ", random()); saved = setstate(saved); (void) random(); (void) random(); } 

每次调用initstatesetstate返回一个指向前一个状态数组的指针。 要返回到该状态,您需要将setstate作为参数调用并将返回的指针存储在某处(可能指向相同的指针,如此处所示)。 您还需要有两个不同的状态数组,或者您只需要反复设置相同的数组 - 在上面的示例中, saved的初始值来自对initstate第二次调用,即,它是在第一次打电话 (第一次调用可能会返回一些内部数组,但是对于与所需数组大小一致的结果,我认为最好自己创建两个数组。)

  •  *state = *setstate(state); 

    只复制状态的第一个字节

  • 随机数生成器实际上每次都会更改状态数组

保持原始arrays方便。

 #include  #include  #include  int main(int argc, const char * argv[]) { char state[256]; char* oldstate; printf("Run 1 : "); oldstate = initstate(123, state, 256); for (int i=1; i < 10; i++) { printf("%ld ", random()); } setstate(oldstate); printf("\nRun 2 : "); initstate(123, state, 256); setstate(oldstate); for (int i=1; i < 10; i++) { setstate(state); // load preserved state printf("%ld ", random()); setstate(oldstate); random(); // this simulates a call to random() from outside } printf("\n"); return 0; } 

哦,我根本不会这样做。 制作您自己的RNG并让它接受状态作为参数。