对于多人游戏,我需要在所有参与设备上生成相同的随机数序列。显然,这是通过在所有设备上使用相同的种子来实现的。当random()
被调用到应该在所有设备上产生相同序列的例程之外时会出现问题。因此,在此例程中,我尝试使用setstate
来保留状态数组。据我了解man random(3)
,在此例程之外调用random()
则不应更改序列。
但是,以下代码不会为Run 1和2生成相同的输出:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
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");
答案 0 :(得分:1)
在第二个循环中,您调用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();
}
对initstate
或setstate
的每次调用都会返回指向之前状态数组的指针。要返回到该状态,您需要将setstate
作为参数调用,并将返回的指针存储在某处(可能指向相同的指针,如此处所示)。您还需要有两个不同的状态数组,或者只是反复设置相同的数组 - 在上面的示例中,saved
的初始值来自对 second 的调用{ {1}},即它是第一次调用中设置的状态数组。 (第一次调用可能会返回一些内部数组,但是对于与所需数组大小一致的结果,我认为最好自己创建两个数组。)
答案 1 :(得分:1)
*state = *setstate(state);
仅复制州的第一个字节
随机数生成器实际上每次都在更改状态数组
保持原始阵列的便利。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
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并让它接受状态作为参数。