在金字塔结构中生成随机玩家优势(PHP)

时间:2009-05-28 15:42:55

标签: php random

对于在线游戏(MMORPG),我想创建具有随机强度值的角色(玩家)。字符越强,这种情况就越少。

示例:

  • 12,000名1名球员
  • 10,500名2名球员
  • 8,500名3名球员
  • 6,000名4名球员
  • 3,000名5名球员

实际上,我需要从1.1到9.9的浮动渐进强度值,但是对于这个例子,用整数强度来解释它更容易。

你知道如何用PHP编写代码吗?当然,我需要mt_rand()来生成随机数。但是我怎样才能实现这种金字塔结构呢?

它有什么功能?根函数,指数函数,幂函数或对数函数?

提前致谢!

它应该如下图所示:

Pyramid graph http://img7.imageshack.us/img7/107/pyramidy.jpg

6 个答案:

答案 0 :(得分:5)

您可以使用对数函数模拟分布,例如您描述的分布。以下将返回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()函数的名称

答案 1 :(得分:3)

最简单的方法是为随机数提供“带”。在你的例子中,你有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

您还可以使用您允许的每个波段的“最大”数量来对这样的函数进行参数化,并且当波段被填充时,它将被包含到下一个最低的现有波段中(除​​了底部波段,它将被包含到下一个最高的)确保只有一定数量的随机分布。

编辑从我的评论中添加:

要获得浮动范围金字塔结构,最佳函数很可能是对数。公式:

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 :(得分:2)

我认为,

workmad3有一个开始,但有一个问题 - 你需要跟踪你的水桶大小以及它们是否已满。随机数生成器不保证这一点。你需要分配你的桶值(强度)和大小(人数),并让你的随机生成器告诉你哪个桶放弃了玩家 - 如果那个桶已满,'溢出'到下一个低点。 / p>

至于为给定的强度值分配铲斗尺寸,这是一个棘手的问题(我认为你真正在做什么)。您所需分布的特征至关重要。如果你想要一个线性下降(金字塔形状提示),那么表格的一行

strength = max_strength - m(number_characters)

会奏效。改变m的值会改变线路下降的速度,并且基本上会限制你的最大总字符数。如果你正在寻找一种更复杂的强度值下降的方法,你可以使用抛物线或双曲线 - 这些曲线有点复杂,但会给你非常不同的特性。

答案 3 :(得分:0)

类似这样的事情

<?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是最弱的。

当然这是基本的,你会想要重构这个以使用循环而不是硬编码开关,但你明白了这一点:)

答案 4 :(得分:-1)

生成0到40000之间的随机数,如果它在0到12000之间,则指定强度1,在12000和22500之间指定2等。

编辑:对于0到10之间的渐进值,使用0到100之间的随机数的平方根,然后从10减去

  • rand - &gt;车力量
  • 0-1 - &gt; 9.9 - &gt; 9(1%)
  • 2-4 - &gt; 9 - &gt; 8(2%)
  • ...
  • 81 - 100 - &gt; 1 - 0(19%)

对于1.1和9.9之间的结果,公式将为伪代码

强度= 10 - sqrt(兰特(1..79))

答案 5 :(得分:-1)

在这种情况下使用百分比可能最容易。

从您的示例中可以看出(稍后将转换为数组以便于使用):

$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数组,如果你需要调整百分比。