In my (Java Android) game, I spawn coins at random positions.
Coins can appear at one of 6 positions horizontally across the screen (2 max per horizontal level).
What I do is create a random number between 0 and 5 for the first coin, then I want generate another random number excluding the position of the first coin.
So, for example, coin 1 is spawned at a random position between 0 and 5 - so let's say 4.
Then the next coin needs to be able to choose between 0-3 or 5. (basically 0-5 excluding 4).
I have managed to do it, but it's not very elegant and I'm sure there must be a better/cleaner way to achieve this, however, it escapes me.
The random(int number) method in the code below simply returns a random int from 0 to number-1 (uses nextInt) and randomBool() just returns a random boolean
Also, please bear in mind that I don't want to use any technique that keeps re-generating a random number if the one it produces is equal to the one we are trying to avoid.
code
//Return a random number between 0 and 5 excluding the specified number
private int getRandomExcluding(int excludedNumber){
//If previous position was 0 then generate a number between 1 and 5
if (excludedNumber==0){
return random(5)+1;
}
//If position was 5, then generate and return number from 0-4
else if (excludedNumber==5){
return random(5);
}
//If number isn't 0 or 5 (then it is in range of 1-4 use a random bool to determine
// if we are going to get a number less than or greater than the number we are excluding
//True - get number lower than excluded number
else if(randomBool()){
//Excluded number is 1
if (excludedNumber==1){
return 0; //Only posibility
}
//Excluded number is > 1
else {
//Return a random number between 0 (inclusive) and the excluded number (exclusive)
return random(excludedNumber);
}
//False - get number higher than the excluded number (between exludedNumber+1 (inclusive) and 6(exlusive))
else {
return random(6-(excludedNumber+1))+(excludedNumber+1);
}
}
-
1Use a set of possible values, removing each as it's selected.Dave Newton– Dave Newton2015年05月31日 15:01:22 +00:00Commented May 31, 2015 at 15:01
-
3One way is to fill a list with the valid values, shuffle it, and return the first two elements.assylias– assylias2015年05月31日 15:01:49 +00:00Commented May 31, 2015 at 15:01
-
I like this idea, I'm guessing this would be in the form of an array of length 5 and maybe a switch on excludedNumber, which would populate the array with the relevant values (so, case 0 would populated with 1,2,3,4 & 5, case 1 with 0,2,3,4 & 5 etc), and then just generate a random number between 0 and 5 and go to that index of the array to retrieve the value?! maybe you could post your idea as an answer if there is a better way to put it into action than my interpretation?! Thanks!!!! –Zippy– Zippy2015年05月31日 20:18:41 +00:00Commented May 31, 2015 at 20:18
3 Answers 3
You could populate a list and shuffle it:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Collections.shuffle(numbers);
int coin1 = numbers.get(0);
int coin2 = numbers.get(1);
1 Comment
shuffle(numbers, new SecureRandom) for an optimal distribution, often important for a game.Try this solution:
private int getRandomExcluding(int excludedNumber){
int num = random(5);
return num >= excludedNumber ? num+1 : num;
}
It simply generates the random number from 0 to 4 and if it's great or equal to the excluded number, it adds one. This way all five possible numbers are uniformly distributed (if your RNG produces uniformly distributed numbers).
3 Comments
Solution: (you can change List<Integer> excludes to int... excludes if you prefer this type of input)
/**
* Get a random number between a range and exclude some numbers
*
* @param start start number
* @param end end number
* @param excludes list of numbers to be excluded
* @return value between {@code start} (inclusive) and {@code end} (inclusive)
*/
private int getRandomWithExclusion(int start, int end, List<Integer> excludes) {
Collections.sort(excludes); // this method only works with sorted excludes
int random = start + new Random().nextInt(end - start + 1 - excludes.size());
for (int exclude : excludes) {
if (random < exclude) {
break;
}
random++;
}
return random;
}