Removing a number from a Java RNG range?

I am currently using Java RNG Random r = new Random() , and it generates a new integer from 0 to 5 in a while loop.

 while (someBoolean == false) { int i = r.nextInt(6); .... } 

What I would like to do is remove a number from the range (e.g. 4) so ​​that the RNG still generates a new number between 0 and 5, excluding one of the values.

My best bet is this:

  while (someBoolean == false) { int i = r.nextInt(6); if (i == removedInt) { continue; } .... } 

However, I am worried that this could lead to lengthy runs in my code, where the RNG constantly returns a number that I don't want.

[ For clarity; the return number is a column in a Connect4 grid or a 2D int array. The method randomly places the movements in the columns until the column is full, and at that moment I no longer want to play in this column. ]

Any help is appreciated :)

+6
source share
4 answers
 ArrayList<Integer> myInts = new ArrayList<Integer>(); myInts.add(1); myInts.add(2); myInts.add(3); myInts.add(4); int i = myInts.get(r.nextInt(myInts.size())); // 1,2,3,4 myInts.remove(3); int j = myInts.get(r.nextInt(myInts.size())); // 1,2,4 

The code selects a random entry from the allowed list of integers.

PS Note that if you have a large range of numbers, creating an ArrayList from thousands and thousands of integers might not be the best idea.

+2
source

Although you can use List list the numbers you want to generate and exclude / delete the one you want to exclude, this is only effective for small ranges. If you want to generate a random number in a large range, this solution becomes quite inefficient and impracticable.

Solution using only 1 Random.nextInt() call

If you want to generate random numbers in the range 0..5 inclusive, you can do this with r.nextInt(6) .

If you want to exclude a number, for example. 4 , this means that the range is less than 1, so use r.nextInt(5) , and if the result is an excluded number, return the maximum allowable max 5 (because it will never be generated because you used max - 1).

It looks like this:

 // Returns a random number in the range 0..5 (0 and 5 included), 4 excluded public int nextRand() { int i = r.nextInt(5); return i == 4 ? 5 : i; } 

Common decision

Here is a general solution that takes min , max and excluded numbers as parameters:

 /** * Returns a random number in the range min..max both included, but never the excluded. */ public int nextRand(int min, int max, int excluded) { if (max <= min || excluded < min || excluded > max) throw new IllegalArgumentException( "Must be: min <= excluded <= max AND min < max"); int i = min + r.nextInt(max - min); // r is a java.util.Random instance return i == excluded ? max : i; } 

So, for example, if you call nextRand(0, 5, 3) , it returns only a random number, which is one of 0, 1, 2, 4, 5 .

+3
source

Hope this helps you in your situation. This does not exclude any numbers, but instead decides where to make the movement in the original value obtained from a random number.

  //Change these to what you want int numberColumns = 7; int numberRows = 6; /** * A way for my snippet to determine what column has a piece in its very top spot. */ boolean[][] hasPiece = new boolean[numberRows][numberColumns]; /** * Get a random number between 0 and numberColumns - 1 and set it equal * to the column you want the computer to place it in. */ int columnToPlace = (int) (0 +Math.random()*numberColumns); /** * A boolean check to determine what side of the chosen column to check first. * This way it doesn't always check to the left or right first. */ if(Math.random() < 0.5){ //Forwards for loop to start at the initial random number given. for(int runner = columnToPlace; runner < numberColumns; runner++){ if(!hasPiece[0][runner]){/**Check First Row And Next Column To The Right For A Piece.*/ columnToPlace = runner;/**If there is no piece their set it equal to that number/empty column.*/ break;/**Break out of the loop*/ } } }else{ //Reversed for loop to start at the initial random number given. for(int backwardsRunner = columnToPlace; backwardsRunner > 0; backwardsRunner--){ if(!hasPiece[0][backwardsRunner]){/**Check First Row And Next Column To The Left For A Piece.*/ columnToPlace = backwardsRunner;/**If there is no piece their set it equal to that number/empty column.*/ break;/**Break out of the loop*/ } } } //The final number/empty column the computer will make it move in. System.out.println(columnToPlace); 

Using this method, you can probably get a decent AI that doesn't just make random moves. This is a good place to start noticing runner loops. If you have a way to check a piece of computer to the left or right of a random column, you can add logic that will make a wiser decision.

0
source

Your brain is fixed on the idea that numbers from random () should be the same numbers that you are actually using for strings or something else. Separate a simple serial number from what it represents using a small array:

 Vector validColumns = new Vector(6); for (int i = 0; i < 6; i += 1) { validColumns.add(i); } . . . c = validColumns[r.nextInt(validColumns.size())] 

In ... you delete and add columns as needed.

0
source

Source: https://habr.com/ru/post/982388/


All Articles