0

I need to create a player with 3 properties:

  • Life (must be a random integer from 1 to 100);
  • Attack (must be a random integer from 1 to 100);
  • Defense (must be a random integer from 1 to 100); But the total sum of all properties must be 200 (Life + Attack + Defense = 200). No more or less. I’ve tried to make something like this:
public function initPlayer(){
        $life = random_int(1, 100);
        $attack = random_int(1, 100);
        $lifeAttack = $life + $attack;
        if($lifeAttack >= 100) {
            $defense = 200 - $lifeAttack;
        } else {
            $defense = random_int(1, 100);
        }
        echo $life . '-' . $attack . '-' . $defense;
    }

But it works correctly only if the sum of two params is equal or more than 100.

SlimBoy Fat
  • 71
  • 1
  • 3
  • 1
    Does this answer your question? [How to make 5 random numbers with sum of 100](https://stackoverflow.com/questions/7289136/how-to-make-5-random-numbers-with-sum-of-100) Also: https://stackoverflow.com/questions/2640053/getting-n-random-numbers-whose-sum-is-m AND: https://stackoverflow.com/questions/16883419/generate-random-numbers-of-which-the-sum-is-constant – ikiK Aug 31 '21 at 12:32
  • I saw these answers but they doesn't work in my case. Or I can't understand how to aply them in my case. – SlimBoy Fat Aug 31 '21 at 12:43

4 Answers4

1

That's basically because $lifeAttack must be greater than 100 to meet all your conditions. You could recurse when it isn't, like this:

public function initPlayer()
{
    $life = random_int(1, 100);
    $attack = random_int(1, 100);
    $lifeAttack = $life + $attack;
    if($lifeAttack >= 100) {
        $defense = 200 - $lifeAttack;
    } else {
       $this->initPlayer();
       return;
    }
    echo $life . '-' . $attack . '-' . $defense;
}

Of course you can do the same without recursion. Perhaps it would be nice to return these values from the function?

KIKO Software
  • 15,283
  • 3
  • 18
  • 33
1

If the three values of life + attack + defense are to be real random numbers in the range 1..100, then the total is only 200 with a very low probability. When the third value is calculated, it is no longer random.

The correct solution is: The 3 values have to be determined again and again until the total is equal 200.

for($sum = 0;$sum !== 200;){
   $life = random_int(1, 100);
   $attack = random_int(1, 100);  
   $defense = random_int(1, 100);
   $sum = $life + $attack + $defense;
}

var_dump($life,$attack,$defense,$life + $attack + $defense);

Output example:

int(65) int(77) int(58) int(200)
jspit
  • 7,276
  • 1
  • 9
  • 17
1

check this algorithm, that produce an array of values in a defined range with a defined sum :

function generate_values($total, $range_min, $range_max, $nb_values) {
    // impossible conditions
    if($total < $range_min*$nb_values || $total > $range_max*$nb_values) {
        return null;
    }

    $values = [];
    
    for($i=0; $i<$nb_values; $i++) {
        $current_total = $total - array_sum($values);
        
        // the last value is the remaining total
        $value = $current_total;
        if( $i < ($nb_values-1) ) {
            $current_range_min = max($range_min, $current_total - ($nb_values-$i-1)*$range_max);
            $current_range_max = min($range_max, $current_total - ($nb_values-$i-1)*$range_min);
            $value = rand($current_range_min, $current_range_max);
        }
        
        array_push($values, $value);
    }
    
    shuffle($values);
    return $values;
}

// test with your needs
for($i=0; $i<10; $i++) {
    $values = generate_values(200, 1, 100, 3);
    var_dump($values, array_sum($values));
}
techws
  • 108
  • 8
0

This would be a case where only 2 numbers would be I inherently random. I would recommend first randomizing life from 1 to 100, and set the upper bound for attack as 100 -$life (I.e. 1 to 100 - $life) . Finally, defense would be pre-determined as 100 - lifeAttack.

Nicholas Dullam
  • 291
  • 1
  • 9