我正在尝试以程序方式在2D网格上生成一个世界。对于随机数生成,我正在使用单个 全局java.utils.Random 实例和一个种子。
像这样:
public class Game {
private static final int SEED = 1111;
private static final Random RANDOM = new Random(SEED);
private static final int roomsCount = generateRandomNumberOfRooms();
}
一切正常,直到我编写了此方法:
public ArrayList<XYCoords> generateRandomCoordinates(){
ArrayList<XYCoords> coords = new ArrayList<>(roomsCount);
for(int i = 0; i < roomsCount; i+=1) {
XYCoords xy = new XYCoords(RANDOM.nextInt(WIDTH), RANDOM.nextInt(HEIGHT));
coords.add(xy);
}
return coords;
}
当我执行它时,会得到 XYCoordinates 的列表,但是它们都有相同的两个 X 和 Y 值,例如(11 ,20)或(12,5)...等所有房间都降落在同一地点。在我看来,for循环中对 RANDOM.nextInt()的调用不会更新实例RANDOM的状态。
在我称为RANDOM.nextInt()的所有其他函数中,它都能正常工作。其中一些也用于循环。问题仅在于此功能。它直接在main()中使用一次,而不嵌套在任何地方。
有谁知道问题可能在哪里?如果需要,我可以上传更多代码,但是我认为这无关紧要。
答案 0 :(得分:2)
不必要的行为1 :每次运行的应用程序都以相同的顺序生成相同的值。原因是您的RANDOM
对象用种子实例化。尝试以下调整:(删除种子,允许Random
为您提供随机值):
public class Game {
private static final Random RANDOM = new Random();
private static final int roomsCount = generateRandomNumberOfRooms();
}
如果由于某种原因需要种子,则可以尝试在每次启动时更新种子。
澄清种子的实际作用:
(请注意,如果您提供了种子,也可以从构造函数中设置种子)
setSeed
公共无效setSeed(长种子)
设置此随机种子 使用单个长种子的数字生成器。总合同 setSeed是它更改此随机数生成器的状态 对象,使其处于与之前完全相同的状态 用参数seed作为种子创建。 setSeed方法是 由class Random实现,方法是将种子自动更新为(seed ^ 0x5DEECE66DL)&((1L << 48)-1)并清除haveNextNextGaussian nextGaussian()使用的标志。 setSeed的实现按类 随机碰巧只使用给定种子的48位。一般来说, 但是,覆盖方法可以使用long参数的所有64位 作为种子值。
参数:seed-初始种子
不需要的行为2 :循环后的线完全一样。 XYCoords
类可能将x
和y
声明为static
变量。 解决方案:删除静态声明。由于值是静态的,因此对象在绑定到类时共享这些值。设置的最后一个值是在所有XYCoords
对象上进行迭代时将获得的值。
通常,这是两种情况的混合,导致结果始终是相同的值。