【问题标题】:Best way to generate random number between x and y but not between a and b在 x 和 y 之间而不是在 a 和 b 之间生成随机数的最佳方法
【发布时间】:2012-12-14 14:02:47
【问题描述】:

我有一个 1000x600 像素的画布。我想在画布外生成精灵(但分布均匀)。 检索 (-500, -500) 和 (1500, 1100) 之间但不在 (0, 0) 和 (1000, 600) 之间的随机值的最佳方法是什么?我知道可以使用 while 循环来生成数字,直到它们在范围内,但这似乎是多余的。谢谢。

【问题讨论】:

    标签: javascript random range


    【解决方案1】:

    如果你想生成一个介于 -500 和 1500 之间的数字,不包括 0 到 1000,你可以只生成一个介于 0 和 1000 之间的数字(0 - -500 + 1500 - 1000)。

    如果小于500,则减去500;如果数字大于或等于 500,则加 500。

    或者,更笼统地说:

    function randomInt(outerMin, outerMax, innerMin, innerMax)
    {
        var usableRange = innerMin - outerMin + outerMax - innerMax,
        threshold = innerMin - outerMin,
        num = Math.floor(Math.random() * (usableRange + 1));
    
        if (num < threshold) {
            return num - threshold;
        } else {
            return num - threshold + innerMax;
        }
    }
    
    randomInt(-500, 1500, 0, 1000);
    

    对于二维点,您必须更有创意。首先,您生成两个位于禁止区域内的点,然后将这些值传播到好的区域:

    function randomVector(outer, inner)
    {
        var innerWidth = inner.right - inner.left,
        innerHeight = inner.bottom - inner.top,
        x = Math.floor(Math.random() * (innerWidth + 1)),
        y = Math.floor(Math.random() * (innerHeight + 1)),
        midx = Math.floor(innerWidth / 2),
        midy = Math.floor(innerHeight / 2);
    
        if (x < midx) { // left side of forbidden area, spread left
            x = x / midx * (inner.left - outer.left) - inner.left;
        } else { // right side of forbidden area, spread right
            x = (x - midx) / midx * (outer.right - inner.right) + inner.right;
        }
    
        if (y < midy) { // top side of forbidden area, spread top
            y = y / midy * (inner.top - outer.top) - inner.top;
        } else { // bottom side of forbidden area, spread bottom
            y = (y - midy) / midy * (outer.bottom - inner.bottom) + inner.bottom;
        }
    
        // at this point I'm not sure how to round them
        // but it probably should have happened one step above :)
        return {
            x: Math.floor(x),
            y: Math.floor(y)
        }
    }
    
    randomVector({
        left: -500,
        top: -500,
        right: 1500,
        bottom: 1100
     }, {
        left: 0,
        top: 0,
        right: 1000,
        bottom: 600
     });
    

    重要

    这是因为你的“禁止”区域之外的区域在它们各自的维度上是相等的,即padding-top == padding-bottom &amp;&amp; padding-left == padding-right

    如果这会有所不同,则分布不再均匀。

    【讨论】:

    • 我认为这不能解决这种情况下的问题,因为禁区是二维的。
    • 不行,这行不通,我只需要对 x 执行一次函数,对 y 执行一次。 (具有适当的值)
    • @Philipp Sam 是对的,该函数必须为每个轴执行两次 :)
    • 但您只想排除 x AND y 在禁区内的那些位置。当其中只有一个在该区域内时,这很好(它将是该区域正上方、下方或旁边的一个点)。
    • @Sam 好的,我想我们可以开始了 :) 我已经做了一些快速测试,但如果有任何问题,请告诉我。
    【解决方案2】:

    生成一个介于 0 和 1000 之间的随机数,如果超过 500,则添加 500(或分别为 600),如果不否定它。

    【讨论】:

      【解决方案3】:

      您可以计算一组允许的矩形,而不是一组禁止的矩形。要在任何允许的矩形内获得一个随机位置,您首先选择一个随机矩形,然后在该选定矩形内选择一个随机位置。

      当矩形的大小不相等时,您需要按面积加权,否则较小的矩形将比较大的矩形具有更高的密度(200x100 的矩形需要是 10x20 矩形的 100 倍)。

      【讨论】:

        【解决方案4】:

        只需生成 (0,0) 和 (1,1) 之间的数字,然后使用一些线性函数进行映射。

        否则,将您希望随机坐标落入矩形的区域划分为矩形。假设您获得了 N 个这样的矩形。这些矩形中的每一个都可以通过将 (0,0) 和 (1,1) 之间的随机生成器的输出映射到该矩形来填充(这是一个线性映射)。

        【讨论】:

          猜你喜欢
          • 2018-04-21
          • 2011-05-22
          • 2017-02-22
          • 1970-01-01
          • 1970-01-01
          • 2012-01-07
          • 1970-01-01
          • 1970-01-01
          • 2016-01-01
          相关资源
          最近更新 更多