使用 min/max 和固定时间生成 40 个随机间隔

Generating 40 random intervals with a min/max and fixed time

我正在制作一款总游戏时间为 180 秒的游戏,在这 180 秒内 40 项需要 随机出现 。听起来很简单吧?有一个问题:项之间的最小延迟不能小于 1 秒,也不能高于 10 秒。

到目前为止我得到的是:

const config = {};
config.squidAppearances = 40;

const spawnTimeLastSquid = 180 - 2;
const fixedDelay = spawnTimeLastSquid / config.squidAppearances;
// Fixed delay would be 4.5
const maxDiff = Math.floor(fixedDelay);

let values = [];
let squidIntervals = [];

for (let i = 0; i < (config.squidAppearances); ++i) {
  // Here's the formula:
  const plusOrMinus = Math.random() < 0.5 ? -1 : 1;
  const offset = Math.random() * maxDiff * plusOrMinus;
  let current = (fixedDelay * i + offset);

  if (values.length > 1) {
    var prev = values[values.length - 1];
    if ((current - prev) > 10) current = prev - 10;
    if ((current - prev) < 1) current = prev + 1;
    // I'm saving the delay for each squid so I can do setTimeout()
    squidIntervals.push(current - prev);
  } else {
    // Spawn time would be this:
    squidIntervals.push(fixedDelay * i + offset);
  }
  // Save values so we can use the previous value on next iteration
  values.push(current);
}
// Last squid delay
squidIntervals.push(180 - spawnTimeLastSquid);

console.log(values);

(或 fiddle

检查您的控制台,每次 运行 您都会得到非常不同的结果。有时它看起来像它的工作,但大多数其他时间生成时间不分布在 0(秒)和 180 之间,或者数组中每个项目的延迟为 1000。

我在这里做什么?

好吧,这是我的看法。 您可以将其复制粘贴到控制台并查看输出。(第一个输出未定义,没问题);

let secondsFromStart;
let secondsFromAnotherItem;
setInterval(() => {
    if (typeof secondsFromStart !== 'undefined') secondsFromStart++;
    if (typeof secondsFromAnotherItem !== 'undefined') secondsFromAnotherItem++;
}, 1000);
createItem = () => {
  console.log('random item created at ' + secondsFromStart + ' seconds from the start of the game and ' + secondsFromAnotherItem + 'seconds since last item was created');
  secondsFromAnotherItem = 0;
  if (typeof secondsFromStart === 'undefined') secondsFromStart = 0;
}
generateRandomItem = (min, max) => {
    let timeout = Math.floor((Math.random() * (min - max)) + max);
    return new Promise((resolve, reject) => {
        if (secondsFromStart > 180) {
            reject('Time is up');
        }
        setTimeout(() => {
            setTimeout(() => {
                createItem();
                generateRandomItem(min, max);
            }, timeout);// worst case scenario - item is created at last second
        }, min);// dont even start the clock until minimum time has passed
    });
}
generateRandomItem(1000, 10000);

我认为问题出在这几行

if ((current - prev) > 10) current = prev - 10;
if ((current - prev) < 1) current = prev + 1;

改成

应该可以
if ((current - prev) > 10) current = current- 10;
if ((current - prev) < 1) current = current + 1;

谢谢

我会这样做:

为每个 squid 生成间隔 [1;10]​​,计算总时间,通常 > 180,因此现在您可以减少随机间隔直到达到持续时间限制:

function generateObjects() {
    let r = [];
    let s = 0;
    for (let i=0; i<40; i++) {
        let d = Math.floor(Math.random()*10) + 1;
        r[i] = d;
        s += d; // total duration
    }
    while (s >= 180.) {
        let d = Math.random();
        let i = Math.floor(Math.random()*40);
        if (r[i]-d >= 1.0) {
            r[i] -= d;
            s -= d;
        }
    }
    // to be sure here you could have similar to above while (s < 180.) loop and increase random interval to fully fill 180 seconds, if you want
    return r;
}

function drawObjects(objs) {
    let c = document.getElementById('canvas').getContext('2d', {alpha: false});

    c.fillStyle = 'whitesmoke';
    c.fillRect(0, 0, 360, 10);

    c.fillStyle = 'black';
    let s = 0;
    for (let i=0; i<objs.length; i++) {
        s += objs[i];
        c.fillRect(2*s, 0, 1, 10);
    }
}

drawObjects(generateObjects());
<canvas id="canvas" width="360" height="10"></canvas>