KeenSeeker99
KeenSeeker99

Reputation: 109

Improving random generation function

I am doing a small app that involves the system randomly generating objects. Here's how it goes

Each objects has a field that specifies the "type" of the object. Let's say fire, ice, wind (not the actual thing in the app though) Each type has a field called "possibilities" that determines the possibilities of that type being generated. The default value for this field is of course 1/numberOfTypes Another field of a type is its "order" in the list, let's say fire is 1st and ice is 2nd and wind is 3rd.

My naive solution to this is to use Math.floor(Math.random()*100 / defualtPossibilities) and match it with type.oder So if the random value is .75, and there are three types, Math.floor(...) will return 2 which means that the object is an ice object.

However, I meet with some potential problems:

  1. It is possible to alter the possibilities value of each type. In this case I can still generate a random number and use a loop to check each type.order*type.possibilities until it exceeds the random number. But I'm not sure whether there's a better way of doing it.

  2. When you change one type.possibilities, the other type. possibilities must change in accordance to keep the total possibilities 100. I plan to do this by divide evenly the amount of change to all the other types. Is it a good approach.

I'm sorry if I'm vague at some points but please help me ^-^

Thank you all!

Upvotes: 1

Views: 151

Answers (1)

Denys Séguret
Denys Séguret

Reputation: 382132

Here's a short solution :

 float weights[]; // each >0

 public int nextIndex() {     
     float sum =0;
     for (int i=weights.length; i-->0;) sum+=weights[i];
     float r = myrandom.nextFloat()*sum;
     sum = 0;
     for (int i=0; i<weights.length-1; i++) {
         sum += weights[i];
         if (r<sum) return i;
     }
     return weights.length-1;
 }

You can change each weight independently. The idea is simply to recompute the sum of the weights instead of supposing it's 100.

Obviously, for the best performances you could precompute the sum.

Upvotes: 1

Related Questions