Создание случайных сильных игроков в структуре пирамиды (PHP) - PullRequest
4 голосов
/ 28 мая 2009

Для онлайн-игры (MMORPG) я хочу создавать персонажей (игроков) со случайными значениями силы. Чем сильнее символы, тем меньше должно быть такого рода.

Пример:

  • 12 000 сил 1 игроков
  • 10500 сил 2 игрока
  • 8500 сил 3 игрока
  • 6000 сил 4 игрока
  • 3000 сил 5 игроков

На самом деле мне нужны плавающие, прогрессивные значения силы от 1,1 до 9,9, но для этого примера было проще объяснить это целочисленными значениями силы.

У вас есть идея, как я могу написать это на PHP? Конечно, мне нужно mt_rand () для генерации случайных чисел. Но как мне достичь этой пирамидальной структуры?

Что это за функция? Корневая функция, экспоненциальная функция, степенная функция или логарифмическая функция?

Заранее спасибо!

На графике это должно выглядеть так:

Пирамидальный график http://img7.imageshack.us/img7/107/pyramidy.jpg

Ответы [ 6 ]

5 голосов
/ 28 мая 2009

Вы можете смоделировать распределение, такое как описанное вами, используя логарифмическую функцию. Следующее вернет случайное значение силы в диапазоне от 1,1 до 9,9:

function getRandomStrength() 
{
    $rand = mt_rand() / mt_getrandmax();
    return round(pow(M_E, ($rand - 1.033) / -0.45), 1);
}

Распределение по 1000 прогонов (где S - это значение прочности в полах):

S | Count
--+------
1 -  290
2 -  174
3 -  141
4 -  101
5 -  84
6 -  67
7 -  55
8 -  50
9 -  38

Примечание:

Этот ответ был обновлен, чтобы включить значение прочности 1,1 (которое не было ранее из-за округления) и исправить имя функции mt_getrandmax()

3 голосов
/ 28 мая 2009

Самый простой способ сделать это - указать «полосы», куда должно идти случайное число. В вашем примере у вас есть 15 игроков, поэтому вы можете иметь:

rand < 1/15, highest strength
1/15 < rand < 3/15, second highest
3/15 < rand < 6/15, third highest
6/15 < rand < 10/15, fourth highest
10/15 < rand < 15/15, lowest strength

Вы также можете параметризовать такую ​​функцию с помощью 'max' номера каждой полосы, которую вы разрешаете, и когда полоса заполнена, она включается в следующую наименьшую существующую полосу (кроме нижней полосы, которая будет включена в следующий самый высокий), чтобы обеспечить только определенное число каждого со случайным распределением.

Редактировать добавление из моих комментариев:

Чтобы получить структуру пирамиды с плавающей точкой, наилучшей функцией, скорее всего, будет логарифм. Формула:

11 - log10(rand)

будет работать (с log10, являющимся логарифмом с основанием 10), так как это даст диапазоны вроде:

1 < rand < 10 = 9 < strength < 10
10 < rand < 100 = 8 < strength < 9
100 < rand < 1000 = 7 < strength < 8
etc.

, но значение rand должно быть в диапазоне от 1 до 10 ^ 10, что потребует большой случайности (больше, чем может справиться большинство случайных генераторов). Чтобы получить случайное число в этом диапазоне, вы можете умножить их вместе. 3 случайных числа могут управлять этим:

11 - log10(rand1 * rand2 * rand3)

с rand1, имеющим диапазон 1-10000, и rand2 и rand3, имеющим диапазон 1-1000. Это немного отклонило бы распределение от правильной пирамиды (хотя, скорее всего, в центре были бы цифры), поэтому оно может быть неподходящим.

2 голосов
/ 28 мая 2009

У workmad3 есть начало, я думаю, но здесь есть одна загвоздка - вам нужно отслеживать размеры ваших корзин и определить, заполнены они или нет. Генератор случайных чисел не гарантирует этого. Вам нужно будет назначить значения ваших корзин (силы) и размеры (количество человек), и позволить вашему генератору случайных чисел сказать вам, в какую корзину нужно уронить игрока - если она заполнена, «переполниться» до следующей нижней.

Что касается назначения размеров ковша для данного значения силы, это хитрый момент (и я думаю, над чем вы действительно работаете). Характеристики вашего желаемого распределения имеют решающее значение. Если вам нужна линейная капля (на которую намекает форма пирамиды), линия вида

strength = max_strength - m(number_characters)

будет работать. Изменение значения m изменит скорость, с которой обрывается линия, и в основном ограничит максимальное количество символов. Если вы ищете более изощренный способ снижения значений силы, вы можете использовать параболическую или гиперболическую кривую - они немного сложнее, но дают вам совершенно другие характеристики.

0 голосов
/ 28 мая 2009

В этом случае, вероятно, проще всего использовать проценты.

Из ваших примеров будет примерно (преобразован в массив для простоты использования позже):

$strength[1] = .3;  // start with a key of 1
$strength[2] = .26;
$strength[3] = .21;
$strength[4] = .15;
$strength[5] = .08;

Таким образом, вы можете сгенерировать случайное число с помощью mt_rand() и разделить его на максимально возможное значение, чтобы получить число от 0 до 1:

$rand = mt_rand() / mt_getrandmax(); // rand is some random value between 0 and 1

Затем вы можете использовать оператор foreach для выделения каждого случая:

$comparisonPercentage = 1;
$selectedLevel = count($strength); // covers the case where mt_rand() returns 0
foreach($strength as $level => $currentPercentage) 
{
    $comparisonPercentage -= $currentPercentage;
    if ($rand >  $comparisonPercentage) 
    {
        $selectedLevel = $level;
        break;
    }
}

// $selectedLevel contains the level you need...

Если вы делаете это таким образом, вам нужно изменить массив $strength, только если вам нужно поиграть с процентами.

0 голосов
/ 28 мая 2009

как то так

<?php

$rand = rand(1,10);

switch ($rand) {

case 1:
echo "band 1";
break;

case 2:
case 3:
echo "band 2";
break;

case 4:
case 5:
case 6:
echo "band 3";
break;

default:
echo "band 4";
break;

}

?>

Группа 1 - самая сильная, а группа 4 - самая слабая.

Конечно, это просто, вы можете изменить его, чтобы использовать циклы вместо жестко закодированных переключателей, но вы поняли:)

0 голосов
/ 28 мая 2009

генерирует случайное число от 0 до 40000, если его от 0 до 12000, назначают силу 1, между 12000 и 22500 назначают 2 и т. Д.

Редактировать: для прогрессивных значений от 0 до 10 используйте квадратный корень из случайного числа от 0 до 100, затем вычтите, если из 10

  • ранд -> сила
  • 0-1 -> 9,9 -> 9 (1%)
  • 2-4 -> 9 -> 8 (2%)
  • ...
  • 81 - 100 -> 1 - 0 (19%)

Для результатов между 1.1 и 9.9 формула будет в псевдокоде)

сила = 10 - кв. (Ранд (1..79))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...