我有一系列图片。每张图片都有一个“稀有”键,告诉我它是“常见”,“不常见”还是“罕见”。例如,数组可能看起来像这样:
Array
(
[0] => Array
(
[image] => photo1.jpg
[rarity] => common
)
[1] => Array
(
[image] => photo2.jpg
[rarity] => uncommon
)
.
.
.
[x] => Array
(
[image] => photo(x).jpg
[rarity] => rare
)
)
我想从列表中选择'y'个图像,几乎就像创建一副牌,但是用图像代替。当然,稀有性定义了选择卡的可能性。我该怎么做呢?我想我是从array_rand()开始的,但我仍然坚持到底去哪里。
编辑澄清:阵列中的每个图像只能出现在最后一层中。
答案 0 :(得分:7)
我会用三个不同的数组做到这一点。每个稀有类型一个。
让我们说概率是:普通= 70%,不常见= 25%,罕见= 5%。
您的三个数组是$commonArray
,$uncommonArray
和$rareArray
。
您的目标牌组是$deck
。
然后生成1到100之间的随机数,并选择三个数组中的一个:
<?php
$rand = rand(1,100);
if ($rand <= 70) {
$cardArray = &$commonArray;
} else if ($rand <= 95) {
$cardArray = &$uncommonArray;
} else {
$cardArray = &$rareArray;
}
现在从所选数组中选择一张卡片:
$chosen = array_rand($cardArray);
$deck[] = $cardArray[$chosen];
unset($cardArray[$chosen]); //remove the chosen card from the array to prevent duplicates
重复此操作,直到$deck
达到您想要的大小。
答案 1 :(得分:2)
这是我的尝试。在$chances
中,您必须定义一个普通的,不常见的或罕见的卡片将被选择作为0-100之间的int出现在牌组中的机会。此外,你必须提供甲板大小。
提供卡片独特且无法在同一套牌中多次出现的答案:
$cards = array(/* your array from above */);
$deck = array();
$deck_size = 52;
$chances = array('common' => 90, 'uncommon' => 30, 'rare' => 5);
$max_attempts = 3;
$tmp_cards = $cards; // copied
while(count($deck) < $deck_size) {
$roll = rand(0, 100);
for($a = 0; $a < $max_attempts; $a++) {
$index = array_rand($tmp_cards);
$card = $tmp_cards[$index];
$rarity = $card['rarity'];
$image = $card['image'];
if(isset($deck[$image])) {
continue;
}
if($roll <= $chances[$rarity]) {
// if the roll is lower than the required probability
// we can put this card in
$deck[$image] = $card;
unset($tmp_cards[$index]); // delete the card so it's not picked again
break;
}
}
}
$deck = array_values($deck);
<强>更新强>
改进了代码并为所有分支机构提供了明确的退出。
答案 2 :(得分:1)
让我们说普通类别比稀有类别多5倍,而罕见情况比稀有类别高出2倍。
对于每个图像,它是8个中的5个变化是常见的,8个中的2个变得不常见,8个中的1个很少见。
因此:
if ((rand() % 8) < 5)
{
$key = array_rand($common);
return $common[$key];
} else {
etc.
答案 3 :(得分:0)
我会将存储稀有度的系统从文本更改为数字,而低数字则更为罕见。通过这种方式,您可以在下次使用数字扩展系统,而不是发明更多类别,如“超稀有”或“超罕见”。这个数字可以是体重年龄。数字越高,越常见。如果类别的所有频率总和达到100%,您可以轻松编写Sjoerd答案的通用版本。
此外,不是将所有卡存储在一个阵列中,就像Sjoerd在上面的答案中所发布的那样,是让每个类别都是自己的阵列。您可以将所有卡存储在数据库中,并具有按其稀有性对其进行分组的功能。
答案 4 :(得分:0)
为了讨论的缘故,我会假设你的稀有物是用整数加权的。 (它不需要像数学那样工作。事实上,如果你愿意,你可以使用实际概率0≤p≤1。但它使解释更容易。)这是如果你在一个牌组中有一张普通的,不常见的,罕见的牌并且用替换牌进行抽牌,那么在 x + y + z 抽出之后你应该画出 x , y 不常见, z 稀有卡片。
如果所有牌都有相同的可能性并且你的套牌 x 普通, y 不常见,并且 z ,你也可以获得相同的预期抽奖罕见的。因此,让我们使用它来查找从每个类别中抽取卡片的真实概率。
假设您的套牌中有 C 普通, U 不常见,以及 R 稀有卡片。统一概率卡的等效套牌将有 C·x 普通卡, U·y 不常见卡,以及 R·z 稀有卡,总计 T = C·x + U·y + R·z 卡。所以选择普通卡的概率是 Pc = C·x / T 等。
确定类别后,您只需选择一张卡片即可。他们都有同样的可能性,所以只需选一个。
您可以直接将其转换为程序(伪PHP):
$Cx = count($common_card_array) * odds of common x
$Uy = ...
$Rz = ...
$Total = $Cx + $Uy + $Rz
$rnd = rand(1, $Total);
if ($rnd <= $Cx) {
$rnd2 = rand(0, count($common_card_array) - 1)
return $common_card_array[$rnd2];
}
$rnd = $rnd - $Cx;
if ($rnd <= $Uy) {
...
}
...