- 210
- 1
- 19
Решил тут одевать зомби в случайный шмот из массива, сначала сделал выборку через MathHelper.getRandomIntegerInRange(random, min, max), потом поразмыслил и пришел к выводу, что хочу неравномерный рандом, убывающий вверх, чтобы, например, крутой алмазный шмот выпадал реже, чем какой-нибудь кожаный). После некоторых поисков - проблема была в том, что я даже не смог сформулировать строку для поиска (либо гугл просто меня не понял) - решил написать собственную функцию. И вот что у меня получилось:
Возможности:
1. Можно задать любой диапазон (int) чисел (включая отрицательные).
2. Можно задать любые (double) массы пределов вероятности.
3. Предусмотрена защита от ошибок в строке вызова функции для облегчения выявления ошибок.
4. Можно использовать зерно мира.
Уверен, что я изобрел велосипед, что этот велосипед - инвалид, что есть более элегантные способы достичь желаемого результата, но мне эти способы неизвестны. Буду рад, если кому-то моя функция окажется полезной.
Код:
/** ## Линейный убывающий рандом ##
* @param minNumber - наименьший номер выборки
* @param maxNumber - наибольший номер выборки (> minNumber)
* @param minWeight - минимально возможная вероятность (> 0)
* @param maxWeight - максимально возможная вероятность (> minWeight)
* @param rand - передача рандома извне на случай привязки к сиду мира, например
* @return - случайное число из диапазона
*/
public static int decreasingRandom(int minNumber, int maxNumber, double minWeight, double maxWeight, Random rand){ // для значений: 0, 9, 0.2, 1.0
if(maxNumber <= minNumber){
Console.out().println("[DecreasingRandom] Error: maxNumber (" + maxNumber + ") must be > that minNumber (" + minNumber + ").");
return minNumber;
}
if(minWeight <= 0){
Console.out().println("[DecreasingRandom] Error: minWeight (" + minWeight + ") must be > 0.");
return minNumber;
}
if(maxWeight <= minWeight){
Console.out().println("[DecreasingRandom] Error: maxWeight (" + maxWeight + ") must be > minWeight (" + minWeight + ").");
return minNumber;
}
int count = 1 + maxNumber - minNumber; // всего чисел
double[] chances = new double [count]; // массив вероятностей для чисел
int[] numbers = new int[count]; // массив возможных чисел
double step = (maxWeight - minWeight) / (count - 1); // шаг (разница вероятности между соседними числами) = размер диапазона / количество чисел - 1
double sum = 0D; // общая масса вероятностей для всех чисел
for(int i = 0; i < count; i++){
numbers[i] = minNumber + i; // заполняем массив возможных чисел значениями из заданного диапазона
chances[i] = maxWeight - (step * i); // заполняем массив убывающей последовательностью вероятностей с шагом step
sum += chances[i]; // складываем все вероятности всех чисел
}
double choose = rand.nextDouble() * sum; // вычисляем случайное число из общей суммы вероятностей
sum = 0D; // сбрасываем сумму вероятностей
for(int i = 0; i < count; i++){
sum += chances[i]; // снова складываем последовательно вероятности всех чисел
if(sum >= choose){
return numbers[i]; // как только найденное случайно число становится меньше - найден номер результата, возвращаем его
}
}
// итог (если расчеты не приведут к результату, выдаем ошибку в консоль и минимальный из возможных результатов) 0
Console.out().println("[DecreasingRandom] Error: Function doesn't make a choice correctly. Check it.");
return minNumber;
}
1. Можно задать любой диапазон (int) чисел (включая отрицательные).
2. Можно задать любые (double) массы пределов вероятности.
3. Предусмотрена защита от ошибок в строке вызова функции для облегчения выявления ошибок.
4. Можно использовать зерно мира.
Уверен, что я изобрел велосипед, что этот велосипед - инвалид, что есть более элегантные способы достичь желаемого результата, но мне эти способы неизвестны. Буду рад, если кому-то моя функция окажется полезной.