我会尽力解释这一点。我需要根据每个项目中剩余的项目数量生成一个随机值(颜色)。
假设我有5种颜色,每种颜色有10个可用点:
Red = 10
Blue = 10
Green = 10
Yellow = 10
Black = 10
我想得到第一个随机的颜色,每种颜色都有相同的机会,因为它们都有10个斑点。然后,如果选择的第一个值是红色,则列表将看起来像
Red = 9
Blue = 10
Green = 10
Yellow = 10
Black = 10
然后,下一个随机值将使红色的权重略低,因为其他颜色中可用的斑点更高。假设红色再次被选中,那么列表将看起来像:
Red = 8
Blue = 10
Green = 10
Yellow = 10
Black = 10
因此,下一轮比赛将使瑞德的体重更低。
基本上,我希望每个点都有平等的机会被平等地选中,但要均匀地分配点(不按顺序排列)。
颜色可以大于或小于5,可用的斑点可以多达1000个。数据将被存储在DB中,但每秒可能有多个点请求,因此关于如何存储该数据的任何建议也将受到赞赏。一旦请求了一个点,它就会从颜色组中删除。
非常感谢!
由于您想在数据库中存储点,因此我不得不采用其他解决方案之外的另一种方法。
为了对其进行建模,使多个线程可以使用一种可用的颜色,您还可以有一个斑点表,将它们的颜色指示为集合或外键,以及一个具有唯一密钥和默认NULL的租约id。
您可以通过首先更新尚未使用租约id(uuid)租用的随机行来选择随机元素。从那时起,其他请求无法再选择该请求,您可以通过租约id进行选择查询,以了解它的颜色。这将确保不会出现竞争条件,并且您可以通过基于行的锁定同时为多个客户端提供服务。
有了10000个点,你可以存储一种颜色和一个租赁id,所以它将小于80kB。整个表将始终处于缓存中。
您可以将项目视为权重,然后选择一个随机值并将其与权重进行比较。遍历列表并从随机值中减去权重,直到它小于列表概率。在下一次迭代中,当项目被使用时,概率会发生变化,直到它为空。
x = random([0.0, 1.0])
for i in 0..n
if x < probabilities[i]
choose(i)
break
else
x -= probabilities[i]
end
end
您可以尝试这样的方法。假设你有一个像你提到的数组,数据来自数据库:
red => 100
green => 200
blue => 50
将所有组合颜色的值相加(在这种情况下为350)。选择一个介于1和1之间的随机值。
$randValue = rand(1, 350);
然后使用循环逐渐减去颜色的值,直到剩下0或负数:
foreach ($colors as $key => $value) {
$randValue = $randValue - $value;
if ($randValue < 1) {
$pickedColor = $key;
// and substract 1 from this color in the DB
break;
}
}
所以,在这种情况下,如果$randValue
是124,你会得到绿色。