我正在尝试模拟野生口袋妖怪的遭遇。如公式所述:
The rate of Pokémon encounter is determined from a simple mathematical formula:
1 in (187.5 / ( x )) per step.
Let x equal the a value which determines how rare the Pokémon is. The higher the encounter rate,
the more common the Pokémon is.
Encounter-rate Table
Encounter type Encounter rate
Very common 10
Common 8.5
Semi-rare 6.75
Rare 3.33
Very rare 1.25
我想在每次按下按钮后运行此概率。我如何用rand()
模拟这个?
我会这样做的
映射rand()
rand() / (float)RAND_MAX
Rand()
返回一个从0到RAND_MAX
的值,所以这个公式将0 -> RAND_MAX
映射到0 -> 1
(float)用于使RAND_MAX
成为一个浮点数,因为rand()
返回的值是int
,c ++中的int / int
返回int
(rand() / (float)RAND_MAX) * 10
如果将结果乘以10,它将映射来自rand()
的0 -> 10
(rand() / (float)RAND_MAX) * 187.5
这将映射来自rand()
的0 -> 187.5
在187.5中的1
我们从rand()
绘制了0 -> 187.5
的值
现在,每当我们调用rand()
时,它将从0->187.5
返回一个随机数
为了简化,我们说我们从rand()
映射0 -> 200
rand()
将返回一个低于100的数字,因为0 - > 200之间的每个数字都有相同的返回机会(例如rand()
可以返回25.67或100.9或140.6)
( (rand() / (float)RAND_MAX) * 187.5 ) < 1
按照同样的原则,返回的数字小于1的概率为187.5
最终解决方案
我们仍然缺少187.5 / X中的1
要实现遇到率,您只需要更改0 -> 187.5
To的映射
0 -> 187.5 / X
我们可以看到,如果X很大,则表示存在较高的遭遇率并且187.5变小并且返回的数字具有小于1的可能性,但是如果遇到率较低则X变小并且187.5变大(较低)小于1的机会
最终代码
srand (time(NULL)); // Init rand() with a seed
bool encountered = ( (rand() / (float)RAND_MAX) * (187.5 / x) ) < 1
优化
一位用户指出,使用最后一个代码,你需要为每个事件计算5个rand(),但如果我们稍微调整一下公式,你只能计算1个rand()
通过使用简单的数学,您知道在10/2步骤中发生一次(1)的事件是在(2)中以10个步骤发生两次的事件
因此,在187.5 / X步骤中发生一次(1)的事件以187.5步骤发生(1 * X)
如果我们从0 - > 187.5映射rand()那么对于每个小精灵,我们只用一个rand()就能为它计算一个唯一值
float randomNumber = (rand() / (float)RAND_MAX) * 187.5
bool encountedPokemon1 = randomNumber < 1 * encounter_rate_first_pokemon
bool encountedPokemon2 = randomNumber < 1 * encounter_rate_second_pokemon
使用模运算符。 rand()将返回一个介于0和整数可以容纳的最高值之间的数字。所以rand()%10将返回0到9之间的数字。
(rand()%1875)<= 10应该是187.5次中的1次(或1875中的10次)
如果你还不知道,%会给你余数。所以x%10永远不会大于9。
这是一个reference