【问题标题】:Generate random player strengths in a pyramid structure (PHP)在金字塔结构中生成随机玩家实力 (PHP)
【发布时间】:2009-05-28 15:42:55
【问题描述】:

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

例子:

  • 12,000 实力 1 名玩家
  • 10,500 力量 2 名玩家
  • 8500实力3人
  • 6000实力4人
  • 3000名实力5人

实际上,我需要从 1.1 到 9.9 的浮动渐进强度值,但对于此示例,使用整数强度更容易解释。

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

它是什么功能?根函数、指数函数、幂函数还是对数函数?

提前致谢!

在图表中应该是这样的:

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

【问题讨论】:

  • 根据您在下面的评论,我有一个相关的问题 - 这实际上是 best 发行版吗?许多游戏更多地使用正态分布,这很容易通过将几个随机数相加(掷骰子)来实现。

标签: php random


【解决方案1】:

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

【讨论】:

  • 非常感谢!这正是我一直在寻找的。我以 50,000 次运行开始相同的测试,得到:13404、9356、6565、5051、4113、3435、3048、2643、2385
  • 任何人都知道一本很好的手册来解释数学分布(或分布随机性)????
【解决方案2】:

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

您还可以使用您允许的每个波段的“最大”数量对此类函数进行参数化,当该波段被填充时,它被归入下一个最低的现有波段(除了底部波段,该波段将被归入下一个最高的)以确保每个随机分布的特定数量。

从我的 cmets 编辑添加:

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

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。不过,这会使分布稍微偏离正确的金字塔(我相信更有可能在中心有数字),因此它可能不合适。

【讨论】:

  • 非常感谢!这可能会很好。但是我忘了说我实际上需要从1.1到9.9的浮动强度。所以一个函数应该更好。
  • 我想你可能需要玩一下日志。 log10(rand) 其中 rand 是 1 到 10^10 之间的随机数会起作用,但是在如此大的范围内,你可能会遇到像样的随机数的问题
  • 抱歉,您想要的确切公式实际上是:11 - log10(rand),范围与以前相同。如果您不介意稍微倾斜曲线,您可以做的是将 3 个随机数相乘。 11 - log10(rand1 * rand2 * rand3) rand1 的范围为 1 - 10000,rand 2 和 rand3 的范围为 1 - 1000。这将给出正确的范围,但分布偏斜。
  • 谢谢!这是我想到的。但不幸的是,强度值的分布过于极端:20392、21672、6523、1210、187、15、1 - 这是我在 50,000 次运行中得到的结果。
  • 猜猜分布非常偏斜:)
【解决方案3】:

workmad3 已经开始了,我认为,但有一个问题 - 你需要跟踪你的存储桶大小以及它们是否已满。随机数生成器不能保证这一点。您需要分配您的桶值(强度)和大小(人数),并让您的随机生成器告诉您将玩家放入哪个桶 - 如果该桶已满,则“溢出”到下一个较低的桶。

至于为给定的强度值分配存储桶大小,这是一个棘手的问题(我认为您真正在做的是)。所需分布的特征至关重要。如果你想要一个线性下降(金字塔形状暗示),一个形式的线

strength = max_strength - m(number_characters)

会起作用的。改变 m 的值会改变线路下降的速度,并且基本上会限制您的最大总字符数。如果您正在寻找一种更复杂的方式来降低强度值,您可以使用抛物线或双曲线 - 这些曲线稍微复杂一些,但会给您带来截然不同的特性。

【讨论】:

  • 对不起,我觉得我的描述有点不清楚。如果新用户注册,我只想创建 1 个角色/玩家。金字塔形式应该从所有参与者中出现。所以当 7000 个用户注册后,他们的实力分布应该看起来像一个金字塔。现在更好地描述?
【解决方案4】:

类似的东西

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

当然这是基本的,你可能想重构它以使用循环而不是硬编码开关,但你明白了 :)

【讨论】:

    【解决方案5】:

    在这种情况下使用百分比可能是最简单的。

    从您的示例中大约是(转换为数组以便以后使用):

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

    【讨论】:

    • 啊哈,您已经编辑了问题 - 所以这可能无济于事,因为您必须创建 100 个不同的强度级别!有你想要的数学函数我只需要找到它......
    • 我添加了另一个答案来说明您对问题的更新。我会更新这个,但将来有人可能需要这个来解决类似的问题
    【解决方案6】:

    生成一个介于 0 到 40000 之间的随机数,如果它在 0 到 12000 之间,分配强度 1,在 12000 到 22500 之间分配 2 等等。

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

    • rand -> 强度
    • 0-1 -> 9.9 -> 9 (1%)
    • 2-4 -> 9 -> 8 (2%)
    • ...
    • 81 - 100 -> 1 - 0 (19%)

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

    强度 = 10 - sqrt(rand(1..79))

    【讨论】:

    • 谢谢。是否也有可能创造浮动的、渐进的力量?我实际上需要从 1.1 到 9.9 的强度,它应该具有金字塔形式。
    • 我编辑了我的答案。平方根应该是正确的公式,因为在你的三角形中,面积与高度的平方成正比
    • 听起来不错,但您的函数无法提供高达 9.9 的有效强度值。我认为这个函数会更好:10.9-sqrt(1...96)
    • 即使修正后的函数也不能提供好的值。它们分布不均。在 50,000 次运行中,我得到:8975、8965、7838、6864、5214、4835、3638、2627、1044
    猜你喜欢
    • 1970-01-01
    • 2020-12-23
    • 1970-01-01
    • 2022-08-18
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多