Java Random.nextInt() repeating numbers only in a loop - java

I am trying to procedurally generate a world on a 2D grid. For the random numbers generation I am using a single global java.utils.Random Instance and a seed.
Like this:
public class Game {
private static final int SEED = 1111;
private static final Random RANDOM = new Random(SEED);
private static final int roomsCount = generateRandomNumberOfRooms();
}
Everything worked just fine untill I wrote this method:
public ArrayList<XYCoords> generateRandomCoordinates(){
ArrayList<XYCoords> coords = new ArrayList<>(roomsCount);
for(int i = 0; i < roomsCount; i+=1) {
XYCoords xy = new XYCoords(RANDOM.nextInt(WIDTH), RANDOM.nextInt(HEIGHT));
coords.add(xy);
}
return coords;
}
When I execute it I get the list of XYCoordinates but they all have the same two X and Y values, for example (11,20) or (12, 5)... etc. and all the rooms land on the same spot. It looks to me like the call to RANDOM.nextInt() in the for loop doesn't update the state of the instance RANDOM.
In all other functions that I call RANDOM.nextInt() it works fine. Some of them use for loops too. The problem is only with this function. It is used once directly in main() and not nested anywhere.
Does anyone have any sense of where the problem might be? I can upload more code if you need, but I think it is irrelevant.

Unwanted behaviour 1: each application run generates the same values in the same order. The reason is your RANDOM object which is instantiated with a seed. Try the following adaption: (Removing the seed, allowing Random to give you random values):
public class Game {
private static final Random RANDOM = new Random();
private static final int roomsCount = generateRandomNumberOfRooms();
}
If you need the seed for some reason, you could try to update the seed at each startup.
Clarification what the seed actually does:
(Note that the seed is also set from the constructor if you provide a seed)
setSeed
public void setSeed(long seed)
Sets the seed of this random
number generator using a single long seed. The general contract of
setSeed is that it alters the state of this random number generator
object so as to be in exactly the same state as if it had just been
created with the argument seed as a seed. The method setSeed is
implemented by class Random by atomically updating the seed to (seed ^
0x5DEECE66DL) & ((1L << 48) - 1) and clearing the haveNextNextGaussian
flag used by nextGaussian(). The implementation of setSeed by class
Random happens to use only 48 bits of the given seed. In general,
however, an overriding method may use all 64 bits of the long argument
as a seed value.
Parameters: seed - the initial seed
Unwanted behaviour 2: the cords are all the same after the loop. The XYCoords class probably declares the x and y as static variables. Solution: Remove the static declaration. As the values are static, the objects share these values as they are bound to the class. The last values which are set are the values you will get if you iterate over all of your XYCoords objects.
In general it is a mixture of both things which lead to the result that you get the same values all the time.

Related

How can I maintain probability across multiple executions in Java

Firstly I am not the greatest with Math, so please excuse any ignorance relating to that. I am trying to maintain probability based randomness across multiple executions but I am failing. I have this input in a JSONObject
{
"option1": 25,
"option2":25,
"option3" :10,
"option4" :40
}
This is my function that selects a value from the above JSONObject based on the probability assigned:
public static String selectRandomoptions(JSONObject options) {
String selectedOption = null;
if (options != null) {
int maxChance = 0;
for (String option : options.keySet()) {
maxChance += options.getInt(option);
}
if (maxChance < 100) {
maxChance = 100;
}
Random r = new Random();
Integer randomValue = r.nextInt(maxChance);
int chance = 0;
for (String option : options.keySet()) {
chance += options.getInt(option);
if (chance >= randomValue) {
selectedOption = options.toLowerCase();
break;
}
}
}
}
the function behaves within a reasonable error margin if I call it x amount of times in a single execution ( tested 100+ calls), the problem is that I am running this every hour to generates some sample data in an event-driven app to verify our analytics process/data but we need it to be somewhat predictable, at least within a reasonable margin?
Has anyone any idea how I might approach this? I would rather not have to persist anything but I am not opposed to it if it makes sense or reduces complexity/time.
The values returned by Random.nextInt() are uniformly distributed, so that shouldn't be a problem.
I you would like to make random results repeatable, then you may want to use Random with seed.
Rather than create a new Random() object each time you want a new random number, just create the Random object once per run, and use the Random.nextInt() object once per run.
Looking at the documentation of Random() constructor,
This constructor sets the seed of the random number generator to a
value very likely to be distinct from any other invocation of this
constructor.it only guarantees it to be different
that's a bit of a weaker contract than the number you get from nextInt().
If you want to get the same sequence of numbers on each run, use the Random(long seed) or the setSeed(long seed) method of the random object. Both these methods set the seed of the generator. If you used the same seed for each invocation it's guaranteed that you will get the same sequence of numbers from the generator.
Random.setSeed(long).

Method returns 0

I've made a program that generates a random number but every time it gives back 0.0
Program:
import java.util.*;
public class RandomNumber {
public static void main(String args[]){
double QuantityColors = 5;
double Mastermind = 0;
Random(QuantityColors, Mastermind);
System.out.println(Mastermind);
}
public static double Random(double QuantityColors, double Mastermind){
Mastermind = Math.random();
Mastermind = Mastermind * QuantityColors;
Mastermind = (int) Mastermind;
return Mastermind ;
}
}
I've been searching where the problem is, but the problem is in the return.
a) you are doing nothing with the result of "Random".
b) you can not modify Java argument. See change a functions argument's values?
First of all, you can use a builtin function to generate a next integer with a certain upper bound: Random.nextInt(int). For instance:
Random rand = new Random();
int masterMind = rand.nextInt(QuantityColors);
Instead of writing a Random method yourself.
It is nearly always better to use builtins since these have been tested extensively, are implemented to be rather fast, etc.
Next you seem to assume that Java uses pass-by-reference. If you perform the following call:
Random(QuantityColors, Mastermind);
Java will make a copy of the value of MasterMind. Setting the parameter in a method has no use. The only way to set a value - not encapsulated in an object - is by returning value. So:
MasterMind = Random(QuantityColors, Mastermind);
To make a long story short: the method does not return 0, you simply don't do anything useful with it.
A better solution would thus be to drop the Random method and use:
import java.util.*;
public class RandomNumber {
public static void main(String args[]){
int quantityColors = 5;
Random rand = new Random();
int mastermind = rand.nextInt(QuantityColors);
System.out.println(mastermind);
}
}
Further remarks
In your random method:
public static double Random(double QuantityColors, double Mastermind){
the MasterMind parameter is rather useless since you immediately set it with another value, so you better remove it and use a local variable instead.
Furthermore Java standards say that the name of classes, interfaces, etc. start with an uppercase; the names of methods and variables with lowercase.
Finally it is unclear why you use doubles since all the values you calculate are clearly integral.
It looks like your code would work if you wrote
Mastermind = Random(QuantityColors, Mastermind);
...because Java is pass by value, so calling a function will not change the variable you passed in.

Class Random only Generates 0

Okay
I have The problem that i want to generate 64 numbers between 0 and 1 (that means 0 or 1)
the function i have currently is:
public static int randNr(int max) {
Random r = new Random();
int o = r.nextInt(max);
return o;
}
But it always returns 0.
Is there any way to make that it generates also a 1 ?
EDIT:
the function is located in a different java file than when i calling it!
Two issues:
1) nextInt(max); generates a number from 0 and up to but not including max. My guess is that you're passing 1 as max. Pass 2 and all will be well.
2) Creating a new generator object each time ruins the statistical properties of the generator. You should create one Random instance and (i) either pass into the function or (ii) have the instance stored as a member variable.
This function works fine. You are probably calling it with the wrong arguments. It should be:
randNr(2)
Why? Because it's using the Random#nextInt(max) method, which will return a random integer in the range [0, max-1] (including 0 and max-1).
Note: It's not recommended to create a new Random object each time you call the function. One solution would be to declare the Random object as an static member of the class:
public class Test
{
private static Random r = new Random();
// ...
}
Another solution would be to use the static method Math.random()1:
int o = (int) Math.round(Math.random());
1: Could someone confirm if this method is faster than the OP's one?

A unique 'code' to represent a 2d array

I've made a game that randomly generates mazes, the maze is stored in a 2d array.
each integer in the array represents the number of walls that cell has.
It's based on the java example here: http://rosettacode.org/wiki/Maze
To allow people to share a unique maze i'm trying to find a way to convert the array into a string or an integer that can be generated by one user, copied and then pasted into another game which will then load the same maze.
The user can select the size of the maze up to 25x25 so simply printing each value (2|16|4|20...) would be incredibly long.
If converting it to a 'code' isn't possible are there any other ways it can be done without using a file?
Store the seed for the random number generator. The seed fully determines the output of the random number generator.
Assuming you are using java.util.Random to generate the random numbers, instead of using the default constructor new Random() use
long seed = System.currentTimeMillis();
// store the seed somewhere
// so you can generate the same sequence of random numbers again
Random rng = new Random(seed);
To make a short "code" that can be given to users for sharing, you can convert the number to hex or base 36:
String code = Long.toString(seed, 36); // codes like heeho82h
If you're randomly creating the values for that array, you only need the state of the PRNG that produced those values to re-generate them. That's at the same time the biggest weakness and strength of all pseudo-random number generators.
As most PRNGs don't allow retrieving and setting the state, or have a pretty huge state (a Mersenne Twister has a few kilobyte of state internally), you may want to use the seed instead. Of course, then you must create a new PRNG (or reset an existing one) for level generation.
To make the number human-readable, you should just render it in some number base. Base 10 makes it obvious it's a number and is easiest to generate and parse. Base 16 (hexadecimal) and base 64 yield shorter, more obscure "codes". Padding it to be fixed-length regardless of the actual value is probably a good idea.
You could use Serialization concept to save the state of 2-D array and then retrieve it back using deserialization. Here is the simple Demo to save a 2-D array state and then read it back . I hope it would be of your help:
import java.io.*;
class ArraySerialization
{
ByteArrayOutputStream baos;
ByteArrayInputStream bins;
public void saveState(Object obj)throws Exception
{
baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.close();
}
public int[][] readState()throws Exception
{
bins = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream oins = new ObjectInputStream(bins);
Object obj = oins.readObject();
oins.close();
return (int[][])obj;
}
public static void main(String[] args) throws Exception
{
int arr[][]= {
{1,2,3},
{4,5,7}
};
ArraySerialization ars = new ArraySerialization();
System.out.println("Saving state...");
ars.saveState(arr);
System.out.println("State saved..");
System.out.println("Retrieving state..");
int j[][] = ars.readState();
System.out.println("State retrieved..And the retrieved array is:");
for (int i =0 ; i < j.length ; i++ )
{
for (int k = 0 ; k < j[i].length ; k++)
{
System.out.print(j[i][k]+"\t");
}
System.out.print("\n");
}
}
}
Although it uses a random generator, it is in fact a deterministic process. You can repeat it by knowing the random seed. Just share the random seed, as mentioned by Joni. Anyway, if you want to share the data: a NxN mesh has NxN inner walls, and considering it takes 1 bit to store presence/absence of a wall, you will need NxN bits to store the maze. In this way you can store a 90x90 maze in 1kb.

Extend java.util.Random to control generation of numbers

Hello I have the following tasks:
First, I am given this code that uses a method to generate random numbers 100 times:
public class Q3 {
public static void printDiceRolls(Random randGenerator) {
for (int i = 0; i < 100; i++) {
System.out.println(randGenerator.nextInt(6) + 1);
}
}
public static void main(String[] args) {
Random man = new Random();
printDiceRolls(man);
}
}
Second, I am asked to make a class LoadedDice that extends the Random class:
public class LoadedDice extends Random {
// instance variables - replace the example below with your own
public int nextInt(int num) {
// code right here
return 3;
}
}
Then I am asked to override the public int nextInt ( int num ) and do the following
Override the public int nextInt(int num) method such that with a 50%
chance, the new method always returns the largest number possible
(i.e., num-1), and with a 50% chance, it returns what the Random's
nextInt method would return
I do not quite understand what my overridden method should do in this case.
Suggestions?
Use another Random instance to give you a 50% chance (e.g. nextInt(100) >= 50) then based on that return a constant or a real random.
I guess one way to do this is to use (another?) random number generator with a uniform distribution and set it to return 0 or 1. The 0/1 would be the 50% for you to make your decision upon.... either returning super.nextInt or the max number.
To me, it looks like the nextInt(int) function comes up with a number between 1 and the input. In the root Random class, this function finds a random number within that range. What they want you to do is change that so that half the time it will return a random number in the range, but the other half the time it will give the maximum number.
In the example they gave, you're rolling a dice, so the range is 1-6. Normally, nextInt will find a random number between 1 and 6. But your new function will only do that half the time. The other half the time, it will return 6.
I have an idea on how you can implement that, but it seems like it would be cheating to go that far. ^^;
if(super.nextBoolean())
return num-1;
return super.nextInt(num);
if num<Integer.MAX/2, we can
int x = super.nextInt(num*2);
return Math.min(x, num-1);

Categories