Sign in to follow this  
menyo

[web] [PHP] rand with percentage

Recommended Posts

hi,

I am trying to automaticly generate a tile map. Now let's say i want a 50% chance it makes a tile a grass tile, a 30% chance for a forest and a 20% chance for a mountain.

I could do it like this but there must be some shortcut to this:

let's say 1=grass, 2=forest and 3=mountain.


$type=array('1','1','1','1','1','2','2','2','3','3');
echo $type[rand(0,9)];




problem here is if i want to have something with 4,3% chance i have to build an array with 1000 keys. So i could use:

$type = rand(1,1000);
if ($type > 43)
{
//insert that type
}




Are there other ways to get what i want?

[Edited by - menyo on December 5, 2010 7:25:32 AM]

Share this post


Link to post
Share on other sites
If you have a list of the percentage chance you want for each tile type you could pick a random percentage (from 0-100) and go along your chances array adding up the values until you got to the slot that represents the chance you randomly selected.

Maybe something like this (my php is rusty, so the syntax might be off):


$tile_chances = array( 50, 30, 20 );
$tile_types = array( 1, 2, 3 );

$chosen_value = rand( 0, 100 );
$current_percent = 0;

for ( $i = 0; $i < 3; $i++ )
{
$current_percent = $current_percent + $tile_chances[ $i ];
if ( $current_percent >= $chosen_value )
{
// use tile from $tile_types[ $i ]
}
}



Alan

Share this post


Link to post
Share on other sites
Why not just do:

$Rand = mt_rand(0, 10000) / 100; //creates a number between 0.00 and 100.00

if($Rand < 10.03)
{ //make tile 1; }
elseif($Rand >= 10.03 $$ Rand < 20.22)
{ //make tile 2; }


etc


I'm sure there is a way to improve upon the if/else statements, but its pretty direct and works.

Share this post


Link to post
Share on other sites
You might consider a lottery-ball system. This was copied from some C++ code i wrote a million years ago, but i'm sure you can reappropriate it for PHP:


// given a vector of integer lotto balls, picks an index
// returns 0 otherwise (since there is usually a first index)
int Lotto( std::vector<int> v ) {

// count them all for a total
int total = 0;
for(unsigned int x=0; x < v.size(); x++) {
total += v[x];
}

// short circuit for floating point exceptions
if (total == 0) {return 0;}

// choose one
int pick = int( rand() % (total) );

// find the index it belongs to
int run = 0;
for(unsigned int x=0; x < v.size(); x++) {
int was = run;
run += v[x];
if ( (pick >= was) && (pick < run) ) {return x;} else {continue;}
}

return 0;
}


Share this post


Link to post
Share on other sites
Thnx all,

I am going for the if statement technique. However i was hoping for a quicker approach. I vaguely remember a Pascal program i wrote an age back for school that had something similar but way shorter. The if statement technique ill work fine i guess.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this