以某种方式组织阵列(轮盘赌项目)

时间:2015-01-26 17:51:43

标签: php

我正在努力(可能是简单的)阵列改组/生成算法。

我为轮盘赌游戏(JS / HTML)创建简单的后端(PHP / MySQL)。轮盘赌没有像往常一样的数字值,而是用户可以获胜的4个奖品,分布在轮盘赌轮的12个区段内。

我需要一个像这样的数组:

// Note that PRIZE4 is listed only once as it is valuable prize.
// PRIZE3 is less valuable so it is listed twice, etc.
// Prizes are skipping each other so you should never see two identic prizes next each other.
var items = [PRIZE1, PRIZE2, PRIZE1, PRIZE2, PRIZE1, PRIZE2, PRIZE1, PRIZE2, PRIZE1, PRIZE3, PRIZE4, PRIZE3];

我在这样的SQL表中有奖品:

+----+------------+--------------+
| id | name       | giveaway_cap |
+----+------------+--------------+
|  1 | PRIZE1     |          255 |
|  2 | PRIZE2     |          300 |
|  3 | PRIZE3     |           30 |
|  4 | PRIZE4     |           15 |
+----+------------+--------------+
4 rows in set (0.00 sec)

giveaway_cap确定每个奖项可以赢得多少(我将这些计数存储在不同的表格中),但可以用作每个奖品的重量。

我需要一些算法(最好是PHP),它会根据这个表生成一个如上所述的数组。

感谢。

3 个答案:

答案 0 :(得分:1)

我发现这非常好algorithm在SO上搜索。它根据重量生成随机数。使用它,您的问题的一种方法可以如下:

// This is the function that generates random numbers based on weigth.
function getRandomWeightedElement(array $weightedValues) {
    $rand = mt_rand(1, (int) array_sum($weightedValues));
    foreach ($weightedValues as $key => $value) {
        $rand -= $value;
        if ($rand <= 0) {
            return $key;
        }
    }
}

$items = [ "PRIZE1" => 255, "PRIZE2" => 300, "PRIZE3" => 30, "PRIZE4" => 15];// Array of available prizes. It can be retrieved from the DB.
$total = (int) array_sum($items);// Total. I use it to work out the weight.
$items_w = [ "PRIZE1" => (255 / $total) * 1000, "PRIZE2" => (300 / $total) * 1000, "PRIZE3" => (30 / $total) * 1000, "PRIZE4" => (15 / $total) * 1000];// find out the weight somehow. I just divide number of available items by the total.
$res = [];
$previous = NULL;
while ( count(array_diff(array_keys($items), $res))) {// Loop until the result has all available prizes.
    $res = [];
    for ($i = 0; $i < 12; $i++) {
        while ($previous == ($new = getRandomWeightedElement($items_w))) {}// Two consecutive prizes of the same type aren't allowed.
        $res[] = $new;
        $previous = $new;
    }
}

echo implode(',', $res);

这只是一个解决方案,我确信有多种方法可以解决问题。

注意:我使用的是php 5.4短数组语法,如果你的PHP版本低于PHP 5.4,则用array()替换[]。还要记住,在某些情况下可能会出现问题,例如只剩下一种类型的奖品,或者如果没有两个连续的奖品是相同的话,不可能创建一系列奖品。无论如何,你必须控制这些情况。

希望它有所帮助。

答案 1 :(得分:0)

<?php
$connect=mysqli_connect("localhost","my_user","my_password","my_db");

$sql="SELECT id,name,giveaway_cap FROM table";
$result=mysqli_query($connect,$sql);

$prizes = array();
while($row=mysqli_fetch_array($result)) //iterate 4 times on caps != to 0
{
$count = $row['giveaway_cap'];
    if($count != '0')
    {
    $prizename = $row['name'];
    $prizes[$prizename]=$count;
    }
}

$prizewheel = array();
foreach ($prizes as $prize=>$value) // iterate 600 times if caps !=0
{
$prizewheel = array_merge($prizewheel, array_fill(0, $value, $prize));
}

$finalprize=array();

$f = 0;
while($f < 12) //iterate 12 times is # of caps >= 12,final array
{
$prizename = $prizewheel[array_rand($prizewheel)];
$finalprize[] = $prizename;
$f++;
}
?>

答案 2 :(得分:0)

你可以像这样生成一个随机数组:

$rows = array(
    array(
        'id' => 1,
        'name' => 'PRIZE1',
        'giveaway_cap' => 255,
    ),
    array(
        'id' => 2,
        'name' => 'PRIZE2',
        'giveaway_cap' => 300,
    ),
    array(
        'id' => 3,
        'name' => 'PRIZE3',
        'giveaway_cap' => 30,
    ),
    array(
        'id' => 4,
        'name' => 'PRIZE4',
        'giveaway_cap' => 15,
    ),
);

$output = array();

foreach ($rows as $row) {
    for ($i = 0; $i < $row['giveaway_cap']; $i++) {
        $output[] = $row['name'];
    }
}

shuffle($output);

//to get the next prize
$nextPrizeKey = array_rand($output);
$nextPrize = $output[$nextPrizeKey];

//remove the won prize
unset($output[$nextPrizeKey]);

这样做是为每个奖品giveaway_caps在数组中创建一个单独的元素。然后,当赢得奖品时,您减少了赠品数量,这将减少用户再次获得奖品的机会。

如果您希望数组是静态的,您可以在初始生成后将其保存在数据库或缓存(APC,Memcahche)中。然后,您只需删除用户登陆的每个条目,直到没有任何条目为止。您可以使用array_rand获得下一个奖项,然后从阵列中删除密钥。

我希望这会有所帮助。

MIC