【问题标题】:Generate a random position between 2 corners points在两个角点之间生成一个随机位置
【发布时间】:2018-03-04 09:07:12
【问题描述】:

如果我们有两个对象Vector2,它们代表一个矩形的两个角,一个区域:

Vector2 corner1 = new Vector2(-5, -5);
Vector2 corner2 = new Vector2(5, 5);

如何在这两个向量之间生成一个随机位置(在它创建的矩形中的任何位置)?

我想做的是,与x1x2 的距离与y1y2 的距离相同,并在该范围内随机取值。

但是如果第一个向量是5, 5 而第二个向量是-5, -5 呢?我将不得不添加一个负距离,对吗?

最有效的方法是什么?

【问题讨论】:

  • 你愿意在两个给定点之间生成一个随机点吗?这是简单的分析数学。表示这两点A=[a1, a2]B=[b1, b2]。计算向量B-A=(b1-a1, b2-a2)并生成0到1之间的随机值x。A和B之间的随机点X由坐标X=[a1 + x*(b1-a1), a2 + x*(b2-a2)]给出。

标签: java random position point auto-generate


【解决方案1】:

这是一些示例代码,我将解释它的作用。首先,您需要找到 x1 和 x2 之间的距离,并且 y1 和 y2 之间的距离得到总距离之间的随机值,然后减去该距离的一半,所以如果我们的总距离为 10,我们将得到一个随机数 (0 - 10) 减去 5我们得到范围 -5 到 5。

    int x1 = 5;
    int x2 = -5;
    int y1 = 5;
    int y2 = -5;

    Random rand = new Random();

    int distanceX = Math.abs(x1 - x2);
    int distanceY = Math.abs(y1 - y2);

    int offsetX = (x1 + x2)/2;
    int offsetY = (y1 + y2)/2;

    int randX = (rand.nextInt(distanceX) - (distanceX/2)) + offsetX;
    int randY = (rand.nextInt(distanceY) - (distanceY/2)) + offsetY;

    System.out.println(randX + " " + randY);

你只需要使用 Vector 2 所以

distanceX = Math.abs(corner1.x - corner2.x);

等等... 您可能需要根据 Vector2 包含的内容将整数更改为浮点数。

float randX = ((rand.nextFloat()*distanceX) - (distanceX/2));

【讨论】:

  • 但是假设 x1 等于 100 并且 x2 等于 110。这将给出 10 的 distanceX,这意味着您将获得介于 -5 和 5 之间的 randX,这意味着新的 x 值不会位于矩形区域内,因为这需要一个介于 100 和 110 之间的 randX 值。
  • 好点在这种情况下,您需要获取 x1 和 x2 的平均值并将其添加为偏移量。我更新了我的答案以表示感谢您的提醒。
【解决方案2】:

x 和 y 的计算使用完全相同的方法,所以我们现在只关注 x。

Random rand = new Random();
float x1 = Math.min(corner1.x, corner2.x);
float x2 = Math.max(corner1.x, corner2.x);
float deltaX = x2 - x1;
float offsetX = rand.nextFloat() * deltaX;
float randomX = x1 + offsetX;

这有效地对 x 值进行排序,以便将较小的值称为x1,将较大的值称为x2,并计算它们之间的差异并将其存储在deltaX 中。

然后使用java.util.Random.nextFloat() 计算一个随机值,它返回一个介于 0.0(含)和 1.0(不含)之间的值,并将随机值乘以 delta。这给了我们一个随机值offsetX,它介于零和两个值之间的总差之间。

最后,我们必须将此随机偏移添加到最小 x 值 x1,以便随机点确实位于矩形内,介于 x1(包括)和 x2(不包括)之间。

请注意,我已将其直接写入 Stack Overflow,没有进行任何测试,因此这是您编写一些单元测试以确保您使用的任何方法都适用于各种值(负数、正数)的好机会,两者的混合,零坐标等)。

(顺便说一句,我假设 Vector2 类来自 libgdx API,因为核心 Java 8 API 中没有这样的类。)

更新

即使不使用Math.minMath.max 对值进行排序(我已经通过单元测试确认了这一点),算法也可以工作,因此您可以简化方法:

public static float pickRandomPointBetween(float corner1, float corner2) {
    if (corner1 == corner2) {
        return corner1;
    }
    float delta = corner2 - corner1;
    float offset = rand.nextFloat() * delta;
    return corner1 + offset;
}

同样的方法适用于一对 x 或 y 值,并且无论corner1 的值是否小于、大于或等于corner2 的值都适用。请注意,检查corner1 == corner2 只是一种效率快捷方式,如果您知道您永远不会(或几乎永远不会)将相等的值传递给此方法,则可以将其删除。 (无论是否使用快捷方式,单元测试都会通过。)

要完成您的要求,您将在两个矩形角内创建一个随机点,如下所示:

float randomX = pickRandomPointBetween(corner1.x, corner2.x);
float randomY = pickRandomPointBetween(corner1.y, corner2.y);
Vector2 randomPoint = new Vector2(randomX, randomY);

但是为了保持你的代码整洁,这个逻辑可能应该放在一个专门的方法中,并给出一个清晰的名称。

【讨论】:

    猜你喜欢
    • 2011-07-14
    • 2014-03-20
    • 1970-01-01
    • 2010-10-07
    • 2011-12-16
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    相关资源
    最近更新 更多