根据稀有度创建“卡片组”

时间:2010-07-22 06:44:32

标签: php

我有一系列图片。每张图片都有一个“稀有”键,告诉我它是“常见”,“不常见”还是“罕见”。例如,数组可能看起来像这样:

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()开始的,但我仍然坚持到底去哪里。

编辑澄清:阵列中的每个图像只能出现在最后一层中。

5 个答案:

答案 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) {
    ...
}
...