如何在PHP中还原一个函数?

时间:2016-03-30 07:29:30

标签: php algorithm math

我正在建立一个小游戏,并陷入开发调平系统。我创建了一个函数,它将指数级地增加下一级所需的体验。但是,我不知道如何扭转它,以便我可以投入用户获得的经验并获得相应的水平。

PHP函数

function experience($level, $curve = 300) {

    // Preset value to prevent notices
    $a = 0;

    // Calculate level cap
    for ($x = 1; $x < $level; $x++) {
        $a += floor($x+$curve*pow(2, ($x/7)));
    }

    // Return amount of experience
    return floor($a/4);
}

问题

我想知道如何对此功能进行反向工程,以便为一定数量的体验返回正确的级别。

使用上述功能,我的代码将输出以下内容:

Level 1: 0
Level 2: 83
Level 3: 174
Level 4: 276
Level 5: 388
Level 6: 512
Level 7: 650
Level 8: 801
Level 9: 969
Level 10: 1154

我正在寻找的是一种方法来反转这个功能,这样我就可以输入一定的数量,它将返回相应的水平。

1000经验应该返回9级。

4 个答案:

答案 0 :(得分:15)

将值插入excel并创建趋势线,我得到以下等式:

y = 1.17E-09x^3 - 4.93E-06x^2 + 1.19E-02x + 6.43E-02  

所以你的逆向工程方程式

function level($xp) {
    $a = 1.17e-9;
    $b = -4.93e-6;
    $c = 0.0119;
    $d = 0.0643

    return round($a*pow($xp, 3) + $b*pow($xp,2) + $c * $xp + $d);
}

结果精确到1dp以内,但如果$curve发生变化,则需要重新计算。我也没有超过10级。

其他选项包括缓存查找结果:

$levelXpAmounts = array()

function populateLevelArray($curve=300) {
    $levelXpAmounts[$curve] = array();
    for($level = $minlevel; $level <= $maxLevel; $level++) {
        $levelXpAmounts[$curve][$level] = experience($level);
    }
}

//at game load:
populateLevelArray()

然后,您的反向查找将是

function level($xp, $curve=300) {
    if (!array_key_exists($levelXpAmounts, curve) 
        populateLevelArray($curve);

    for($level = $minlevel; $ level <= $maxLevel; $level++) {
        if ($xp < $levelXpAmounts[$curve][$level]) {
            return $level - 1;
        }
    }
}

这样,对于$curve的每个不同值,只对所有级别进行迭代一次。您还可以使用(很可能更快)查找来替换旧的experience()函数。

注意:自从我编写任何php以来已经有一段时间了,所以我的语法可能有点生疏。对于这方面的任何错误,我事先道歉。

答案 1 :(得分:4)

您可以执行另一个名为level的函数,该函数使用experience函数来查找级别:

function level($experience)
{ 
    for ($level = 1; $level <= 10; $level++) {
        if ($experience <= experience($level)) {
            return $level;
        }
    }
}

function experience($level, $curve = 300)
{
    $a = 0;
    for ($x = 1; $x < $level; $x++) {
        $a += floor($x+$curve*pow(2, ($x/7)));
    }
    return floor($a/4);
}

var_dump(level(1000));

答案 2 :(得分:3)

你可以在这里清楚地学习数学并找到一个反向公式。不确定它是否会是一个简单易用的公式,所以我建议你采用一种易于实现的替代方法。

预先计算你实际想让你的人达到的所有级别的结果(我非常怀疑你需要超过200个级别,因为根据我的估计,你需要数百亿个exp点)。

将所有这些级别存储在数组中:$arr = [0, 83, 174, 276, 388, 512, 650, ...];。现在您的数组已经排序,您需要找到一个适合您的级别的位置。

如果你正在寻找400个exp点,你会看到它应该在第5个位置后插入 - 所以它是5级。即使是简单的循环就足够了,但你也可以编写二进制搜索。

答案 3 :(得分:1)

也许不是最好的方式,但它正在发挥作用。

function level($experience, $curve = 300)
{
    $minLevel = 1;
    $maxLevel = 10;

    for($level = $minLevel; $level <= $maxLevel; $level++)
    {
        if(experience($level, $curve) <= $experience && $experience < experience($level + 1, $curve))
        {
            return $level;
        }
    }

    return $maxLevel;
}