我正在努力(可能是简单的)阵列改组/生成算法。
我为轮盘赌游戏(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),它会根据这个表生成一个如上所述的数组。
感谢。
答案 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