What is the best way to create a random value? - java

I am triying to create random value for my game to show enemies on screen. BUt it some times shows 2 together some times 3 ...I want to ask that which is the best formul for creating random value.. This is my so far random value
random = 1 * (int) (Math.random() * 100);

"BUt it some times shows 2 together some times 3"
Given perfectly random numbers... In every 100 random values from 0 to 99, you'll find an average of 1.0 doubles. A triple will occur on average once for every 10,000 values. Given 10 million random numbers, java.util.Random yeilds the following results on my machine:
Doubles: 99873
Triples: 985
Double Rate: 1 in 100
Triple Rate: 1 in 10152
Source code:
import static java.lang.System.*;
import java.util.Random;
public class Sandbox {
public static final int NUM_ITERATIONS = 10000000;
public static void main(String[] args) {
Random rand = new Random();
int cur;
int last = -1;
int secondLast = -2;
int nDoubles = 0;
int nTriples = 0;
for (int i = 0; i < NUM_ITERATIONS; i++) {
cur = rand.nextInt(100);
if (cur == last) {
nDoubles++;
if (cur == secondLast) nTriples++;
}
secondLast = last;
last = cur;
}
out.println("Doubles: " + nDoubles);
out.println("Triples: " + nTriples);
out.println();
out.println("Double Rate: 1 in " + Math.round(1.0 * NUM_ITERATIONS / nDoubles));
out.println("Triple Rate: 1 in " + Math.round(1.0 * NUM_ITERATIONS / nTriples));
exit(0);
}
}

Actually the creation of genuinely random random numbers is a complex game in its own right. The Wikipedia article on this subject will give you an insight into the complexity that lies therein. Simple approximations such as those outlined above are probably sufficient for game purposes but will, it should be noted, be inclined to be 'streaky' from time to time.

You can use java.util.Random:
Random random = new Random(); // uses System.nanoTime() as seed
int enemies = random.nextInt(100);
Anyway, your approach is also fine, as it is in fact equivalent (behind the scene) with the above.
You can print a sequence of 100 random numbers generated your way and see for yourself that there isn't a problem.

What you use if perfectly fine.
In case you want something simplier you might like to use Random class like this:
Random generator = new Random(seed);
int number = generator.nextInt(100);

...and sometimes 77, sometimes 23, etc, as expected in a uniform distribution?
If you would like a normal distribution instead for your "enemies", so that extremes are less likely, it seems to be there in Java.

Related

Generating a list of random integers (from -1000 to 1000), the number of integers in the list are determined by user input

I have looked through other questions but nothing seems to work. The user chooses how many numbers are in the list and they should be between -1000 and 1000. I tried using two for loops, one displaying the random number and another around that loop repeating the number of time the user enters. For now I tried to just get the loop to work with positive integers up to 1000. When using system print out it finally worked but using the GUI I just get one random number. I used an ArrayList because I thought it'd let me add to it with each loop.
int a;
private void btnSortActionPerformed(java.awt.event.ActionEvent evt) {
try {
a = Integer.parseInt(txtSort.getText());
} catch (NumberFormatException numberFormatException) {
lbl1.setText("Please enter a proper integer");
}
ArrayList<Integer> list = new ArrayList<>();
for (int i=1;i<=1000; i++) {
list.add(i);
}
for (int i=0; i<a; i++) {
txtpane1.setText(String.valueOf(list.get(i)));
}
}
txtSort is the textfield the program gets the number of integers and I'm using Apache NetBeans.
If I am understanding correctly your problem!
You want to generate random numbers user input times which lie between -1000 to 1000.
Then you want to display these all numbers in a Text Pane (Your GUI).
Please look at the following code: (Modified your code)
int a;
private void btnSortActionPerformed(java.awt.event.ActionEvent evt) {
try {
a = Integer.parseInt(txtSort.getText());
}
catch (NumberFormatException numberFormatException) {
lbl1.setText("Please enter a proper integer");
}
StringBuilder stringBuilder = new StringBuilder();
for (int i=1;i<=a; i++) {
int randomNumber = getRandomNumber(-1000,1001);
stringBuilder.append(randomNumber).append(" ");
}
txtpane1.setText(stringBuilder.toString());
}
public int getRandomNumber(int min, int max) {
return (int) ((Math.random() * (max - min)) + min);
}
I have created a method that gives you a random number in range (-1000 to 1000).
I have removed the ArrayList. Instead, I have created a StringBuilder which will store all random numbers in it.
Modify the first Loop which will iterate till user input times (not till 1000 time) and in each iteration, it get the random number and append this random number to string builder.
Removed second loop, no need for it.
After then, just setting StringBuilder text in the GUI.
Random rand = new Random()
final int min = -1000;
final int max = 1000;
// Map (-1000 to 1000) to ​(0 to 2001)
// because 'Random.nextInt' returns
// positive integers only.
final int positiveIntRangeMax = max - min + 1;
final int offsetFromPositiveIntRange = min;
​//loop 'a' times as required by user input
​for (int i=1;i<=a; i++) {
​int newPositiveRandInt = rand.nextInt(positiveIntRangeMax);
​int newRandIntInRange =
​newPositiveRandInt + offsetFromPositiveIntRange;
​list.add(newRandIntInRange);
​}
​txtpane1.setText(list.toString());
My attempt to get the random numbers.
You can generate the numbers like this.
Random r = new Random();
int n = r.nextInt(2001) - 1000;
r.nextInt(2001) returns a number between 0 and 2000 inclusive.
subtract 1000 from that and you get a number between -1000 and 1000 inclusive.
So you can use a loop to generate as many of those as you want. You can also use a stream to generate the numbers and create the list.
specify the number to generate and the range via r.ints
map to an Integer and subtract 1000 as before.
collect into a list.
int count = 10;
List<Integer> numbers = r.ints(count, 0, 2001)
.mapToObj(i -> Integer.valueOf(i - 1000))
.collect(Collectors.toList());
System.out.println(numbers);
Prints something like
[586, 110, 667, 502, 129, -474, 382, -357, -906, -910]
imports required
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

ArrayList contains

I don't really understand what's happening, if someone could explain this to me that would be great.
So, here's my code:
public static ArrayList<Integer> numbers = new ArrayList<Integer>();
public static void main(String[] args){
for(int i =0; i != 90; i++){
System.out.println(generate());
}
}
public static int generate(){
Random random = new Random();
int rand = random.nextInt(89)+1;
while(numbers.contains(rand)){ //<---Here seems to be my problem
rand = random.nextInt(89)+1;
System.out.println("Number: " + rand + " already exists!");
}
numbers.add(rand);
return rand;
}
I am writing a program that generates a random number from 0-90, each of which are different to the last. Unfortunately, it seems that the while loop only returns true.
You're picking from 89 random numbers (1-89 inclusive) and trying to find a unique number each time... but you're calling that 90 times. What do you expect the last iteration to do? (To put it another way - you're trying to squeeze 90 numbers into 89 slots. That's not going to work.) On the last iteration, all the possible values will already be in the list, so the condition of your while loop will always be met, whatever value is randomly chosen on each iteration.
If you wanted the numbers to be between 1 and 90 inclusive, you should be using random.nextInt(90) + 1. The argument to nextInt is the maximum number exclusive to generate - so if you call random.nextInt(3) for example, it will generate 0, 1 or 2.
(There are better ways of doing this, by the way - such as populating the list and then using Collections.shuffle - but I've concentrated on explaining the behaviour of your current code.)
You can do it easily by using collections shuffle
public static ArrayList<Integer> numbers = new ArrayList<Integer>();
for(int i =1; i <= 90; i++){
number.add(i)
}
Collections.shuffle(numbers); // at this point the number are shuffled.
Read about shuffle.

Adding Two Dice 36 Million Times

The Question:
Write a program that rolls two dice and adds their sum 36,000,000 times and prints how many times each sum was calculated.
So obviously I need to get a rand for 6 numbers twice and add them - in a loop for 36 million times, and then get a frequency counter for however many times each sum was found (which ranges from 2 to 12).
Now given the fact that I'm not very experienced in Java, I ran into a couple of problems.
This is the code that I've got so far:
package twodice;
import java.util.Random;
public class TwoDice
{
public static void main(String[] args)
{
int sum;
Random randomNumbers = new Random();
int[] frequency = new int[13];
for (int roll = 2; roll <= 36000000; roll++)
{
++frequency[(1 + randomNumbers.nextInt(6)) + (1 + randomNumbers.nextInt(6))];
}
System.out.printf("%s%10s\n", "Face", "Frequency");
for(int face = 1; face < frequency.length; face++)
{
System.out.printf("%4d%10d\n", face, frequency[face]);
}
}
}
Output:
run:
Face Frequency
1 6001537
2 6003025
3 5997753
4 5997647
5 6000769
6 5999269
7 0
8 0
9 0
10 0
BUILD SUCCESSFUL (total time: 0 seconds)
The problems are that:
1. The sums that are displaying are not 2-12, they're 1-10 (The right number of sums, just not the right sums...
2. The frequencies are only being found for 1-6, not 1-6 + 1-6.
Thanks for all of your help!
EDIT: Solved by Oscar Lopez! Thanks so much man!
For the first problem, the array has the wrong size, this should fix it:
int[] frequency = new int[13];
Also the values at indexes 0 and 1 will always be 0, so the loop should start at face = 2. For the second problem, the program should simulate throwing two dice, not just one as it currently is. Try this:
++frequency[(1 + randomNumbers.nextInt(6)) + (1 + randomNumbers.nextInt(6))];
Also change your for loop. Final code looks like this:
import java.util.Random;
public class TwoDice
{
public static void main(String[] args)
{
Random randomNumbers = new Random();
int[] frequency = new int[13];
for (int roll = 1; roll <= 36000000; roll++)
{
++frequency[1 + (randomNumbers.nextInt(6)) + (1 + randomNumbers.nextInt(6))];
}
System.out.printf("%s%10s\n", "Face", "Frequency");
for(int face = 2; face < frequency.length; face++)
{
System.out.printf("%4d%10d\n", face, frequency[face]);
}
}
}
I ran this, and it works as you might expect.

Java Random number but not zero

int num = 10;
Random rand = new Random();
int ran = rand.nextInt(num);
if (ran==0){
ran= ran+1;
}
System.out.println("random : "+ran);
This is what i have coded so far, is there a better way to do this? I feel that this is hard coding when random is 0, I added 1.
The problem with that code is that 1 is twice as likely as other numbers (as your effective result is 1 when nextInt() returns 0 or 1).
The best solution is to just always add 1 and request random numbers from a smaller range:
int rnd = rand.nextInt(num - 1) + 1;
I guess you are trying to get a random number between 1 and 'num'.
a more generic way can be :
int Low = 1;
int High = 10;
int R = r.nextInt(High-Low) + Low;
This gives you a random number in between 1 (inclusive) and 10 (exclusive). ( or use High=11 for 10 inclusive)
Random random = new Random();
int ran = random.nextInt(9) + 1; //10 is maxRandom value for this code. 1-10
you also could do the following:
int randomNumber = 0;
do {
randomNumber = rand.nextInt(maxValue);
} while(randomNumber == 0);
Try this:
int num,max=10,min=1;
Random r=new Random();
num=r.nextInt(max-min)+1;
You'll need this import at the beginning of your file:
import java.util.Random;
Just lower the bound (num variable) by 1 and add 1 to the ran variable
int num = 10;
Random rand = new Random();
int ran = rand.nextInt(num - 1) + 1;
// or decrease num first n-- and then int ran = rand.nextInt(num) + 1
now the bound(limit) is 8 (inclusive for example, the final number is always exclusive) and if it comes 0, it will increase to 1 and if it comes 8, it will increase to 9, which was originally supposed to be the bound.
Don't expect this functionality from Random and do it yourself as you should. One can do pretty much anything with the result - multiply, add (e.g. 2*nextInt(n)+1 for random odd number), use logarithmic scale for musical note frequencies, use a map or enum to obtain random objects ...
Method nextInt(n) is here only to give you n different values (from 0 to n-1). Don't ask more of it, implement the rest by yourself. If I understand your question well, you require numbers 1..9, so you should ask for nextInt(9)+1 to get 0..8 and then add 1.
I hope this explanation helps, I saw many answers, but I didn't like the explanation in any of them.
Try:
int num = 10;
Random rand = new Random();
int ran = rand.nextInt(num) + 1;

How to get a 50/50 chance in random generator

I am trying to get a 50/50 chance of get either 1 or 2 in a random generator.
For example:
Random random = new Random();
int num = random.nextInt(2)+1;
This code will output either a 1 or 2.
Let's say I run it in a loop:
for ( int i = 0; i < 100; i++ ) {
int num = random.nextInt(2)+1 ;
}
How can I make the generator make an equal number for 1 and 2 in this case?
So I want this loop to generate 50 times of number 1 and 50 times of number 2.
One way: fill an ArrayList<Integer> with fifty 1's and fifty 2's and then call Collection.shuffle(...) on it.
50/50 is quite easy with Random.nextBoolean()
private final Random random = new Random();
private int next() {
if (random.nextBoolean()) {
return 1;
} else {
return 2;
}
}
Test Run:
final ListMultimap<Integer, Integer> histogram = LinkedListMultimap.create(2);
for (int i = 0; i < 10000; i++) {
nal Integer result = Integer.valueOf(next());
histogram.put(result, result);
}
for (final Integer key : histogram.keySet()) {
System.out.println(key + ": " + histogram.get(key).size());
}
Result:
1: 5056
2: 4944
You can't achieve this with random. If you need exactly 50 1s and 50 2s, you should try something like this:
int[] array = new int[100];
for (int i = 0; i < 50; ++i)
array[i] = 1;
for (int i = 50; i < 100; ++i)
array[i] = 2;
shuffle(array); // implement shuffling algorithm or use an already existing one
EDIT:
I understand that if you are looking to accomplish exactly 50-50 results, then my answer was not accurate. You should use a pre-filled collection, since it is impossible to achive that using any kind of randomness. This considered, my answer is still valid for the title of the question, so, this is it:
Well, you do not need the rnd generator to do this.
Comming from javascript, I would go with a single liner:
return Math.random() > 0.5 ? 1: 2;
Explanation: Math.random() returns a number between 0(inclusive) and 1(exclusive), so, we just examine weather is larger than 0.5 (middle value). In theory there is a 50% change that does.
For a more generic use, you can just replace 1:2 to true:false
You can adjust the probability along the way so that the probability of getting a one decreases as you get more ones. This way you don't always have a 50% chance of getting a one, but you can get the result you expected (exactly 50 ones):
int onesLeft = 50;
for(int i=0;i<100;i++) {
int totalLeft = 100 - i;
// we need a probability of onesLeft out of (totalLeft)
int r = random.nextInt(totalLeft);
int num;
if(r < onesLeft) {
num = 1;
onesLeft --;
} else {
num = 2;
}
}
This has an advantage over shuffling because it generates numbers incrementally so it desn't need memory to store the numbers.
You have already successfully created a random generator that returns 1 or 2 with equal probability.
As (many) other's have mentioned, your next request, to force an exact 50/50 distributions in 100 trials, does not fall in line with random number generation. As shown in https://math.stackexchange.com/questions/12348/probability-of-getting-50-heads-from-tossing-a-coin-100-times, the realistic expectation of that occurring is only around 8%. So even while you might expect 50 of each, that exact outcome is actually rather rare.
The Law of Large Numbers states that you should close in on expected value as your number of trials increases.
So for your actual question: How can I make the generator make an equal number for 1 and 2 in this case?
The best (humorous) answer I can come up with is: "Run it in an infinite loop."

Categories

Resources