Я работаю над игрой, и в ней я хочу, чтобы рост происходил в геометрической прогрессии - так, например, получение от 2 до 3 человек может занять примерно то же время, что и увеличение от 2 до 3 миллионов человек. Однако я бы хотел, чтобы этот рост был случайным, если это возможно, чтобы сделать его более реалистичным. Пока у меня есть метод, который хорошо работает:
if (buildingCount > populationCount && foodCount > populationCount)
for(int i=1;i<populationCount;i++) {
int randomInt = random.nextInt(1000);
if (randomInt == 42) {
Data.main.setPopulationCount(populationCount+1);
}
}
if ((buildingCount < populationCount || foodCount < populationCount)&&populationCount>2)
for(int i=1;i<populationCount;i++) {
int randomInt = random.nextInt(1000);
if (randomInt == 888) {
Data.main.setPopulationCount(populationCount-1);
}
Однако я понимаю, что это не будет устойчивым. Он работает примерно 60 раз в секунду (с такой величиной), и как только он достигает уровня в миллионы, он может в конечном итоге выполнять миллиарды операций в секунду - многовато для такой простой проверки. Я поставлю его на интервал, если нужно, но я бы предпочел оставить его случайным.
Я попытался найти уравнение для вероятности, но в итоге получил:
Σ (99 ^ r / 1000 ^ (r + 1)) от r = 0 до p (где p = вероятность)
Есть ли простой способ изменить эту вероятность на тест или более простой метод в Java для достижения такой цели.
Если это поможет, я использую LibGdx в качестве движка.
Вы имеете в виду, выберите число, например, 42, и умножьте его на численность населения - например. 3. Это дало бы 126 - слишком большое увеличение, или вы имеете в виду, что есть 1 шанс из 1000 увеличиться на 3 - и в этом случае он упустит популяцию 4 и 5
Если условия строительства и питания соблюдены, шанс разделения (популяция ++) для каждого человека составляет 1/1000. Таким образом, для N человек в среднем будет n / 1000 разделений за тик. Почему бы просто не добавить (n + - случайным образом) / 1000 человек за тик? Случайным образом должно быть нормальное распределение, основанное на n. Даже с 20 людьми вы редко получите случайное = 1500, за +2 популярности за тик, но обычно это будет +0 или +1. Может потребоваться небольшая настройка на начальном этапе игры, когда pop невелик (чтобы не всегда округляться до нуля), но после этого все должно работать нормально.
@leoderprofi Хороший момент, BigInteger может быть решением, но неизменным.




Здесь
с вашим примером 2-3 от 2М до 3М я бы сказал, используйте оператор * 1.5
пример: каждые 60 лет -> человек = человек * 1,5
груша, я не совсем понимаю, что тебе нужно
lio
Но я хочу, чтобы он увеличивался медленно и с приращением, чтобы вы могли видеть, что числа увеличиваются быстрее, но, может быть, до 1000 вы все равно будете видеть увеличение численности населения. В этом методе это будет: 2 -> 3 -> 4 -> 6 -> 9 -> 13 и т. д. И в любом случае это слишком быстро - проверка происходит каждые 1/60 секунды, а не каждые 60 секунд.
Кажется, что, если предположить, что случайные числа распределены равномерно, вы увеличите численность населения в среднем на n / 1000 для численности населения n.
Чтобы подражать этому, было бы неплохо просто разделить populationCount на 500 и использовать ThreadLocalRandom#nextGaussian, чтобы определить, на сколько увеличить populationCount, что позволит вам избавиться от цикла for:
if (buildingCount > populationCount && foodCount > populationCount) {
if (populationCount > 1000) {
int randomNum = (int) ((ThreadLocalRandom.current().nextGaussian() / 2 + 0.5) * populationCount / 500);
Data.main.setPopulationCount(populationCount + randomNum);
} else {
// Original for-loop here for populations less than 1000.
}
}
Для популяции 10,000 это увеличило бы популяцию в среднем на 10 (в данном случае колеблется от 0 до 20, но в пользу среднего значения 10 из-за использования nextGaussian).
Превратите меня в использование гауссовских распределений. Я думаю, что это лучший ответ, поскольку он поддерживает случайность, которую хочет OP, а не постоянный рост.
Явная формула экспоненциального роста: х_t = х_0 * (1 + г) ^ т где t - ваш интервал (в вашем случае 60 интервалов в секунду) а r - ваш темп роста. Итак, формула увеличения одного интервала:
х_1 = х_0 * (1 + г)
где x_0 - предыдущая популяция.
Итак, в основном, вместо того, чтобы перебирать весь ваш подсчет населения на каждом интервале, вы можете просто это (со скоростью роста 0,1%):
Data.main.setPopulationCount(populationCount + Math.floor(populationCount * 0.001f));
Для уменьшения численности населения просто вычтите, а не прибавляйте.
Data.main.setPopulationCount(populationCount - Math.floor(populationCount * 0.001f));
Чтобы интегрировать случайность, вы можете сделать что-то вроде этого:
Data.main.setPopulationCount(populationCount + Math.floor(populationCount * 0.001f * random.nextFloat()));
Таким образом, ваш темп роста будет колебаться от 0% до 100% на каждом приращении.
Тогда останется только поэкспериментировать со скоростью роста.
Эту стратегию следует использовать только тогда, когда популяция превысит примерно 5 * (1 / темп роста), иначе Math.floor сделает его слишком неточным или даже уменьшит любой рост.
В настоящее время вы делаете следующее: у каждого человека есть шанс 1 из 1000 произвести нового человека. Ваш код сходит с ума от больших чисел, потому что вы проверяете всех.
Для больших чисел ваш алгоритм эквивалентен умножению вашего населения на 1,001 (1 + 1/1000). Случайный аспект исчезнет для больших чисел (как объясняет здесь)
Но для небольшого числа действительно важен случайный выбор. Я думаю, что лучший способ справиться с этим - определить уровень популяции, на котором вы используете умножение и на котором вы используете свой метод.
if (buildingCount > populationCount && foodCount > populationCount)
if (populationCount > 10000) { //I use 10000 has population level but do what you want
for(int i=1;i<populationCount;i++) {
int randomInt = random.nextInt(1000);
if (randomInt == 42) {
Data.main.setPopulationCount(populationCount+1);
}
}
}
}
Вместо того, чтобы повторять цикл N раз для вашей популяции и увеличивать его на единицу, почему бы не выбрать число от 1 до 1000 и умножить на N?