Генерация случайной позиции между двумя точками углов
Если у нас есть два объекта Vector2
который представляет 2 угла прямоугольника, область:
Vector2 corner1 = new Vector2(-5, -5);
Vector2 corner2 = new Vector2(5, 5);
Как вы можете создать случайную позицию между этими двумя векторами (в любом месте в прямоугольнике, который он создает)?
То, что я думал сделать, это расстояние от x1
а также x2
и то же самое для y1
а также y2
и сделать случайное значение из этого диапазона.
Но что, если первый вектор 5, 5
и второй вектор -5, -5
? Я должен добавить отрицательное расстояние, я прав?
Какой самый эффективный способ сделать это?
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;
Это эффективно сортирует значения х, так что меньшее значение называется x1
и тем больше x2
и разница между ними рассчитывается и сохраняется в deltaX
,
Затем случайное значение рассчитывается с использованием java.util.Random.nextFloat()
, который возвращает значение от 0,0 (включительно) до 1,0 (исключая) и умножая случайное значение на дельту. Это дает нам случайное значение, offsetX
, который находится где-то между нулем и общей разницей между двумя значениями.
Наконец, мы должны добавить это случайное смещение к минимальному значению x, x1, чтобы случайная точка действительно находилась внутри прямоугольника, где-то между x1 (включительно) и x2 (исключая).
Обратите внимание, что я записал это прямо в Stack Overflow без какого-либо тестирования, так что это хороший шанс для вас написать несколько модульных тестов, чтобы убедиться, что любой используемый вами метод будет работать для различных значений (отрицательное, положительное, сочетание обоих, нулевые координаты и т. д.).
(Кстати, я предполагаю, что Vector2
класс происходит из libgdx API, так как в базовом Java 8 API такого класса нет.)
Обновить
Арифметика работает даже без сортировки значений, используя Math.min
а также Math.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);
Но чтобы сохранить ваш код в чистоте, эта логика, вероятно, должна быть помещена в отдельный метод и иметь четкое имя.
Вот пример кода, я объясню, что он делает. Сначала вам нужно найти расстояние между 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));