Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

creating a "deck of cards" based on rarity

Tags:

php

I have an array of images. Each image has a "rarity" key that tells me whether it's "common", "uncommon", or "rare". So for instance, the array might look something like this:

Array
(
    [0] => Array
        (
            [image] => photo1.jpg
            [rarity] => common
        )

    [1] => Array
        (
            [image] => photo2.jpg
            [rarity] => uncommon
        )
    .
    .
    .

    [x] => Array
        (
            [image] => photo(x).jpg
            [rarity] => rare
        )
)

I want to select 'y' number of images from the list, almost like creating a deck of cards, but with images instead. The rarity, of course, defines how likely that card will be selected. How do I go about doing this? I figure I start with array_rand(), but am stuck as to where to go with it.

EDIT FOR CLARIFICATION: Each image in the array can only occur in the final deck once.

like image 781
saikofish Avatar asked Jan 25 '26 11:01

saikofish


2 Answers

I would do this with three different arrays. One for each rarity type.

Lets say the probabilities are: common = 70%, uncommon = 25%, rare = 5%.

Your three arrays are $commonArray, $uncommonArray and $rareArray.

Your target deck is $deck.

Then you generate a random number from 1 to 100 and choose one of the three arrays:

<?php
$rand = rand(1,100);
if ($rand <= 70) {
    $cardArray = &$commonArray;
} else if ($rand <= 95) {
    $cardArray = &$uncommonArray;
} else {
    $cardArray = &$rareArray;
}

Now choose one card from the selected array:

$chosen = array_rand($cardArray);
$deck[] = $cardArray[$chosen];
unset($cardArray[$chosen]); //remove the chosen card from the array to prevent duplicates

Repeat this until your $deck is the size you want it to be.

like image 174
selfawaresoup Avatar answered Jan 28 '26 01:01

selfawaresoup


Here's my attempt. In $chances you have to define the chances that a common, uncommon or rare card will be chosen to appear in a deck as an int between 0-100. Also you have to provide the deck size.

Presenting an answer where the cards are unique and cannot appear multiple times in the same deck:

$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);

Update

Improved the code and provided definite exits to all branches.

like image 42
Jesse Dhillon Avatar answered Jan 28 '26 02:01

Jesse Dhillon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!