为了账号安全,请及时绑定邮箱和手机立即绑定

Java:随机生成的数字只出现在给定范围的一小部分

Java:随机生成的数字只出现在给定范围的一小部分

炎炎设计 2023-05-17 17:02:03
我正在开发一款游戏,我希望我的敌人在 1-5 秒之间产生延迟。我那部分的代码如下所示:@Override    public void run() {    try {        while (true) {            Random r = new Random();            int cooldownTime = r.nextInt((5000 - 1000) + 1) + 1000;            long lastSpawn = 0;            long time = System.currentTimeMillis();            if (time > lastSpawn + cooldownTime) {                System.out.println(cooldownTime);                addEnemies();                lastSpawn = time;            }如果我对 nextInt 的理解正确,这应该每次都以 1000-5000 毫秒的间隔产生敌人,但我的结果真的很奇怪,我不太明白为什么。这是一个示例,说明如果我打印cooldownTime.25231190109510611168111910521159107110761000139412491070依此类推...似乎第一个敌人真的是随机生成的,而其他敌人总是在 1000 左右。每次都会发生这种情况。有谁知道为什么会这样?我很迷路。
查看完整描述

5 回答

?
呼啦一阵风

TA贡献1802条经验 获得超6个赞

重复调用Random r = new Random();是极其病态的,会破坏生成器的统计特性。(您获得的结果很可能是系统时钟时间的强函数。)

执行一次该步骤,您的结果会好得多。(还有比这更有效的实现延迟的方法 - 考虑sleep- Java 编译器尚未优化 burn 循环。)

另请注意,由于您没有打印每个绘制的数字,因此您的观察结果更加复杂。


查看完整回答
反对 回复 2023-05-17
?
慕森卡

TA贡献1806条经验 获得超8个赞

不确定这是否是您的确切问题,但您在逻辑上遇到了一些问题System.currentTimeMillis()并且只是查看当前总时间而不是时间之间的差异。


此外,您只想在实际执行后寻找一个新的随机值if,这样您就不会Random每次loop迭代都生成一个数字,而是每次生成一个敌人时,您都会为下一个敌人生成一个新的随机值。


这是考虑到所有这些的修改后的代码:


Random r = new Random();

long time = System.currentTimeMillis();

int cooldownTime = r.nextInt((5000 - 1000) + 1) + 1000;

while (true) {

    long timeDifference = System.currentTimeMillis() - time;


    if (timeDifference > cooldownTime) {

        //addEnemies();

        System.out.println(timeDifference); //Prints the time taken for enemy to spawn

        cooldownTime = r.nextInt((5000 - 1000) + 1) + 1000;

        time = System.currentTimeMillis(); //set the initial time again

    }

}

这将生成一个介于 1000 和 5000 之间的随机数,并if在每次延迟后执行该块,重置中的值以if永远执行此操作。


但是,很可能有更好的方法来为您的逻辑添加延迟,就像一些评论指出的那样(sleep),但这是您的方法的更正逻辑。


查看完整回答
反对 回复 2023-05-17
?
MMTTMM

TA贡献1869条经验 获得超4个赞

好吧,首先,您的几个变量是在循环内部创建的。您需要将对象的创建Random以及循环外的lastSpawn和变量移动。cooldown这是因为lastSpawn每次循环执行 0 时变量都会被覆盖,这意味着您总是在检查当前时间是否大于 0。您需要将它存储在循环之外,以便它保留您分配给的最后一个值它。出于同样的原因,cooldown需要在循环之外,因为您在每个循环中都会生成一个新的冷却时间,并且System.currentTimeMillis()总是会比它大,因为System.currentTimeMillis()您可以获得从 1970 年 1 月 1 日开始的系统时间偏移。最后,作为System.currentTimeMillis()由一个 long 表示,您将希望任何与时间相关的变量也很长,否则如果当前时间(以毫秒为单位)对于整数存储来说太高,您最终可能会溢出您的变量。


这是实现您想要做的事情的更好方法:


import java.util.Random;


public class RandomCooldown {

    public static void main(String [] args) {

        Random rand = new Random();

        long start = System.currentTimeMillis();

        long lastSpawn = start;

        long cooldown = getCooldown(rand);


        while(true) {

            long time = System.currentTimeMillis();

            long elapsed = (time - lastSpawn);

            if(elapsed >= cooldown) {

                System.out.println("Adding enemies!");

                cooldown = getCooldown(rand); // only generate a new cooldown once the old cooldown has been surpassed

                lastSpawn = time;

            }

        }

    }


    public static long getCooldown(Random rand) {

        return (long)((rand.nextInt(4000) + 1) + 1000);

    }

}

希望这可以帮助!


查看完整回答
反对 回复 2023-05-17
?
POPMUISE

TA贡献1765条经验 获得超5个赞

这是一个我认为你喜欢的建议。我没有一个,而是两个循环。外循环生成新的敌人,内循环进行更新(不确定这个生成敌人的线程需要更新多少,但包含它以防万一)。


public void run() {

    Random r = new Random();

    // setup 

    while (true) {

        int wait = r.nextInt((5000 - 1000) + 1) + 1000;

        long time = System.currentTimeMillis();

        System.out.println("Adding enemies at " + time

                + ", next add roughly in " + wait + " ms.");

        while (wait + time > System.currentTimeMillis()) {

            try {

                Thread.sleep(30);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

            // update  

        }

    }

}

Random 对象被重用,调用 Thread.sleep(30) 使线程交出控制权 30 毫秒,在此期间 CPU 可以做比忙等待更有用的事情。(顺便说一句,30 不是一个必须使用的神奇数字,而只是我选择的一个数字。您需要试验并找到最适合您游戏的数字。)


打印输出显示发生了什么。


Adding enemies at 1565096018610, next add roughly in 2890 ms.

Adding enemies at 1565096021530, next add roughly in 2301 ms.

Adding enemies at 1565096023863, next add roughly in 4944 ms.

Adding enemies at 1565096028813, next add roughly in 3042 ms.

Adding enemies at 1565096031879, next add roughly in 2661 ms.

... 等等。当您运行此代码时,实际数字当然不会相同但相似。


希望这对您有所帮助,祝您游戏顺利!


查看完整回答
反对 回复 2023-05-17
?
泛舟湖上清波郎朗

TA贡献1818条经验 获得超3个赞

我觉得不错。您可能应该Random()为每次迭代使用相同的实例。请记住:人类没有能力感知随机性。或者,您可以尝试为 Random-Generator 播种(使用Random(long seed)构造函数),以防您的种子发生一些奇怪的事情。



查看完整回答
反对 回复 2023-05-17
  • 5 回答
  • 0 关注
  • 184 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信