PHP随机值,可能来自5个项目,每个项目有多个项目

PHP随机值,可能来自5个项目,每个项目有多个项目,php,Php,我会尽力解释这一点。我需要根据每个项目中剩余的项目数量生成一个随机值颜色 假设我有5种颜色,每种颜色有10个可用斑点: Red = 10 Blue = 10 Green = 10 Yellow = 10 Black = 10 我想得到第一种随机颜色,每种颜色都有相同的机会,因为它们都有10个斑点可用。然后,如果拾取的第一个值为红色,则列表如下所示 Red = 9 Blue = 10 Green = 10 Yellow = 10 Black = 10 然后,下一个随机值的权重将略低,因为其他颜

我会尽力解释这一点。我需要根据每个项目中剩余的项目数量生成一个随机值颜色

假设我有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个。数据将存储在数据库中,但每秒可能会有多个spot请求,因此对于如何存储此数据的任何建议也将不胜感激。一旦请求斑点,它将从颜色组中删除


非常感谢

你可以试试这样的东西。假设您有一个如上所述的数组,其中数据来自数据库:

red   => 100
green => 200
blue  =>  50
在本例中,添加所有颜色的值。在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,则显示为绿色。

您可以将项目视为权重,然后选择一个随机值,并将其与权重进行比较。遍历列表并从随机值中减去权重,直到其小于列表概率。在下一次迭代中,当项目被使用时,概率会发生变化,直到它为空

   x = random([0.0, 1.0])
   for i in 0..n
       if x < probabilities[i]
        choose(i)
         break
       else
         x -= probabilities[i]
     end
    end

由于您希望在数据库中存储点,因此我将采用其他解决方案以外的另一种方法

要对其进行建模,以便多个线程可以使用一种可用的颜色,您还可以使用一个点表,将它们的颜色表示为set键或外键,以及具有唯一键和默认NULL的租约id

通过首先使用租约id uuid更新尚未租约的随机行来选择随机元素。从这里开始,其他请求不能再选择那个一个,您可以通过租约id进行选择查询,找出它是什么颜色。这将确保没有竞争条件,并且您可以使用基于行的锁定同时为多个客户端提供服务


对于10000个点,您可以存储一种颜色和一个租约id,因此它将小于80kB。整个表将始终在缓存中。

没有得到您想要的结果。如果红色=0,会发生什么?那么您尝试了什么来实现这一点?颜色是否总是以相同数量的斑点开始?具体的点也很重要,因为随机数为7,所以取红色7,或者只取一个红色,这样可用的总数就减少了1?@WebChemist是的,每种颜色都有相同的斑点,当选择一种颜色时,该颜色只会减少1,这样随机选择的颜色就不会在一种颜色中选择特定的斑点。我确实考虑过这种方法,但可能有多达200万个斑点可用,同时有数百个线程一旦也许除了MySQL?MySQL和Innodb之外的另一个DB引擎也可以,因为它有基于行的锁定。我认为200万行也不是问题。关键是不要获得比赛条件。