my "Yahtzee" code sometimes throws in a random number - java

Alright so basically I wanted to make a code that would generate numbers until it hit a perfect "Yahtzee" first try. Sometimes it doesn't work and I'm pretty new to coding (which is why this is an abomination) and even newer to SO. I did this just for education but I don't understand why it sometimes doesn't work. About 20% of the time, instead of saying "11111" it will say "11114" randomly. Help me out?
public class IDontKnowWhatImDoing {
public static void main(String[] args) {
int min = 1;
int max = 6;
int randomInt1 = (int)(Math.random() * (max - min + 1) + min);
int randomInt2 = (int)(Math.random() * (max - min + 1) + min);
int randomInt3 = (int)(Math.random() * (max - min + 1) + min);
int randomInt4 = (int)(Math.random() * (max - min + 1) + min);
int randomInt5 = (int)(Math.random() * (max - min + 1) + min);
while(randomInt1 != randomInt2) {
randomInt1 = (int)(Math.random() * (max - min + 1) + min);
randomInt2 = (int)(Math.random() * (max - min + 1) + min);
randomInt3 = (int)(Math.random() * (max - min + 1) + min);
randomInt4 = (int)(Math.random() * (max - min + 1) + min);
randomInt5 = (int)(Math.random() * (max - min + 1) + min);
System.out.println(randomInt1);
System.out.println(randomInt2);
System.out.println(randomInt3);
System.out.println(randomInt4);
System.out.println(randomInt5);
System.out.println();
while(randomInt2 != randomInt3) {
randomInt1 = (int)(Math.random() * (max - min + 1) + min);
randomInt2 = (int)(Math.random() * (max - min + 1) + min);
randomInt3 = (int)(Math.random() * (max - min + 1) + min);
randomInt4 = (int)(Math.random() * (max - min + 1) + min);
randomInt5 = (int)(Math.random() * (max - min + 1) + min);
System.out.println(randomInt1);
System.out.println(randomInt2);
System.out.println(randomInt3);
System.out.println(randomInt4);
System.out.println(randomInt5);
System.out.println();
while(randomInt3 != randomInt4) {
randomInt1 = (int)(Math.random() * (max - min + 1) + min);
randomInt2 = (int)(Math.random() * (max - min + 1) + min);
randomInt3 = (int)(Math.random() * (max - min + 1) + min);
randomInt4 = (int)(Math.random() * (max - min + 1) + min);
randomInt5 = (int)(Math.random() * (max - min + 1) + min);
System.out.println(randomInt1);
System.out.println(randomInt2);
System.out.println(randomInt3);
System.out.println(randomInt4);
System.out.println(randomInt5);
System.out.println();
while(randomInt4 != randomInt5) {
randomInt1 = (int)(Math.random() * (max - min + 1) + min);
randomInt2 = (int)(Math.random() * (max - min + 1) + min);
randomInt3 = (int)(Math.random() * (max - min + 1) + min);
randomInt4 = (int)(Math.random() * (max - min + 1) + min);
randomInt5 = (int)(Math.random() * (max - min + 1) + min);
System.out.println(randomInt1);
System.out.println(randomInt2);
System.out.println(randomInt3);
System.out.println(randomInt4);
System.out.println(randomInt5);
System.out.println();
}
}
}
}
}
}

The problem is in the conditions you use to check whether you have a five of the same number. If a certain condition is already false (the numbers match), you don't enter that look.
For example, if you randomly generate five numbers, where the first two happen to be equal, then randomInt1 != randomInt2 will be false.
You will then never enter the while(randomInt1 != randomInt2) block, and exit with that initial set of numbers, even though you've only checked that the first two are equal, not the other 3. This problem is present at each level of your nested loops.
The direct solution would be to use do-while loops instead (and removing the first number generator block). This allows each pair of numbers to actually be checked at least once.
That is however an inelegant solution. Assuming that you still want to generate five numbers each time (as in Yahtzee, instead of something simpler like generating one die at a time), it would be cleaner to have a single do-while loop. In that, you could have a single block of random number calls instead of redundant ones at different nesting levels. The condition would have it continue looping until all 5 are equal.

You really don't need all that repetitious code. It all boils down to the condition you use for your while loop. You already know that you need 5 of a kind for a Yahtzee and that means that all dice must match the first dice that is rolled so, your while loop
condition can be:
while ((randomInt1 != randomInt2) || (randomInt1 != randomInt3) ||
(randomInt1 != randomInt4) || (randomInt1 != randomInt5)) {
// ........ other code ....
}
This condition keeps the loop running until all dice are of the same value. With this in mind, you can reduce your code to:
int min = 1;
int max = 6;
int randomInt1 = 1;
int randomInt2 = 2;
int randomInt3 = 3;
int randomInt4 = 4;
int randomInt5 = 5;
while ((randomInt1 != randomInt2) || (randomInt1 != randomInt3) ||
(randomInt1 != randomInt4) || (randomInt1 != randomInt5)) {
randomInt1 = (int) (Math.random() * (max - min + 1) + min);
randomInt2 = (int) (Math.random() * (max - min + 1) + min);
randomInt3 = (int) (Math.random() * (max - min + 1) + min);
randomInt4 = (int) (Math.random() * (max - min + 1) + min);
randomInt5 = (int) (Math.random() * (max - min + 1) + min);
System.out.print(randomInt1 + " " + randomInt2 + " " +
randomInt3 + " " + randomInt4 + " " + randomInt5);
System.out.println();
}
System.out.println(" YAHTZEE");
You can however reduce more repetitious code. You really only need one random number generator. By making your dice an array of dice, for example:
int[] dice = new int[5];
boolean yahtzee = false;
while (!yahtzee) {
int count = 1;
for (int i = 0; i < dice.length; i++) {
dice[i] = (int) (Math.random() * (6 - 1 + 1) + 1);
if (i > 0 && dice[i] == dice[i-1]) {
count++;
}
}
if (count == 5) {
yahtzee = true;
}
}
System.out.println(Arrays.toString(dice) + " YAHTZEE!!");
Another way might be by making use of a HashSet since a HashSet will only hold distinct values, for example:
Integer[] dice = new Integer[5];
java.util.Set<Integer> s = new java.util.HashSet<>();
// If all elements are same, size of HashSet should be 1.
// since the HashSet contains only 'distinct' values.
while (s.size() != 1) {
for (int i = 0; i < dice.length; i++) {
dice[i] = (int) (Math.random() * (6 - 1 + 1) + 1);
}
// Put all array elements in a HashSet
s = new java.util.HashSet<>(Arrays.asList(dice));
}
System.out.println(Arrays.toString(dice) + " YAHTZEE!!");

Related

How to find the sum of the numbers that are between the two given integers in Java

I need to write a method of the sum of the numbers that are between the two given integers.
For example, the call sumNums(1,3) should return 6 because 1+2+3 = 6.
The call sumNums(3,1) should also return 6.
So far I have
public static int sumNum(int num1, int num2)
{
int min = Math.min(num1, num2);
int max = Math.max(num1, num2);
int sum = 0;
for(int i = min; i < max; i++)
{
sum += i;
}
sum =+ max;
return sum;
}
any other methods would help, but if there's a way initialize the sum and return it it would help.
public static int sumNum(int num1, int num2) {
int min = Math.min(num1, num2);
int max = Math.max(num1, num2);
int sum = 0;
for (int i = min; i <= max; i++) {
sum += i;
}
return sum;
}
Honestly using java-8 IntStream
IntStream.rangeClosed(1, 3).sum(); //6
using java-7 and below
public static int sumNum(int num1, int num2)
{
int min = Math.min(num1, num2);
int max = Math.max(num1, num2);
int sum = 0;
for(int i = min; i <= max; i++)
{
sum += i;
}
return sum;
}
It's (simple) math:
public static int sumNum(int num1, int num2) {
int min = Math.min(num1, num2);
int max = Math.max(num1, num2);
return max * (max + 1) / 2 - min * (min - 1) / 2
}
You could do something likes this:
return (num1 + num2) / 2.0 * (Math.abs(num1 - num2) + 1);
Your current approach will encounter performance problems the larger the gap between the two integers. There are optimisations you can make.
For example, if you have an odd number of integers:
2 + 3 + 4 + 5 + 6 = 4 + 4 + 4 + 4 + 4
1 + 2 + 3 = 2 + 2 + 2
5 + 6 + 7 = 6 + 6 + 6
See the pattern?
2 + 3 + 4 + 5 + 6 = 4 + 4 + 4 + 4 + 4
= 5 * 4
= (max - min + 1) * ((max + min) / 2)
For an even number of integers:
2 + 3 + 4 + 5 = 3.5 + 3.5 + 3.5 + 3.5
= 4 * 3.5
5 + 6 + 7 + 8 + 9 + 10 = 7.5 + 7.5 + 7.5 + 7.5 + 7.5 + 7.5
= 6 * 7.5
Looking familiar! Let's see if our previous formula works:
2 + 3 + 4 + 5 = (max - min + 1) * ((max + min) / 2)
= (5 - 2 + 1) * ((5 + 2) / 2)
= 4 * 3.5
The formula can be simplified:
(max - min + 1) * ((max + min) / 2) = (max - min + 1) * (max + min) / 2
Therefore:
public static int sumNum(int num1, int num2) {
int min = Math.min(num1, num2);
int max = Math.max(num1, num2);
return (max - min + 1) * (max + min) / 2;
}
Or using math to get it in constant time:
sum = max * (max + 1) / 2 - (min * (min - 1)) /2;
I don't know if you want to learn Java (iterations and streams) or if you are looking for a good solution to a real problem. In the latter case, your problem is a sum of terms of an Arithmetic progression Arithmetic progression.
The sum of its terms starting at from m to n is given by the product of the number of terms (i.e: m - n +1) and the sum of first and last terms the all divided by 2:
(max - min + 1)*(min + max)/2
Not much different from the others but this would be my sollution
public static int sumNum(int num1, int num2) {
if (num1 > num2) {
int temp = num2;
num2 = num1;
num1 = temp;
}
return (num1 + num2) * (num2 + 1 - num1) / 2;
}

How to Make two arrays that randomizes numbers between 10 and 30, and 11 and 30 in Java

I have to make two arrays that randomizes numbers between 10 and 30(first array), 11 and 30(second array) in java. i'm supposed to fill the first and second one in numerical order... how? i haven't started yet and i need to be finished soon.
int[] a = new int[20];
int random = (int)(Math.random()*21+10);
for(int x=0; x<a.length; x++){
System.out.print(random + " ");
}
System.out.println();
for(int i=11; i<=30; i++){
System.out.print(i + " ");
}
}
}
you can use
((Math.random() * ((max - min) + 1)) + min) to get random with limit
int min = 10;
int max = 30;
int[] a = new int[20];
int[] b = new int[20];
for(int i =0;i<a.length;i++) {
a[i]= (int) ((Math.random() * ((max - min) + 1)) + min);
}
max = 31;
for(int i =0;i<b.length;i++) {
b[i]= (int) ((Math.random() * ((max - min) + 1)) + min);
}
this will do

java random numbers must be different [duplicate]

This question already has answers here:
Generating Unique Random Numbers in Java
(21 answers)
Closed 5 years ago.
I'm creating a small program that extracts 3 random numbers, the only condition is that all three numbers must be different from each other, for example: 3,9,3 is not acceptable.
This i my code, i tried it several times and occasionally appear numbers equal to each other.
What is wrong in my code ?
public class Premi {
public static void main(String[] args) {
int num = (int) (Math.random() *10) + 1;
int num2 = (int) (Math.random() *10) + 1;
int num3 = (int) (Math.random() *10) + 1;
boolean first = true;
boolean second = true;
boolean third = true;
while(first) {
if (num!=num2) {
first=false;
} else if (num==num2) {
num = (int) (Math.random() *10) + 1;
}
}
while(second) {
if (num!=num3) {
second=false;
} else if (num==num3) {
num = (int) (Math.random() *10) + 1;
}
}
while(third) {
if (num2!=num3) {
third=false;
} else if (num2==num3) {
num2 = (int) (Math.random() *10) + 1;
}
}
System.out.println(num + "," + num2 + "," + num3);
}
}
Thank you.
Set<Integer> numbers = new HashSet<>();
while (numbers.size() < 3)
numbers.add(((int) (Math.random() *10) + 1));
Using Set here will guarantee that the numbers are not repeating.
And if you're not allowed to use any collections or arrays (I'll reserve my opinion of courses that forbid students to use valid techniques) you can use:
int n1 = (int) (Math.random() * 10) + 1;
int n2;
do {
n2 = (int) (Math.random() * 10) + 1;
} while (n2 == n1);
int n3;
do {
n3 = (int) (Math.random() * 10) + 1;
} while (n3 == n2 || n3 == n1);
The do loop is guaranteed to run at least once.

Make Math.Random loop until specific number is reached

I'm trying to make a program that 'rolls two dice' and combines the number and needs to keep going until a specific number is reached 7 or 11 but every time I run it it keeps going forever.
double total = 0;
while (total != 7 || total != 11) {
DecimalFormat x = new DecimalFormat("#");
double dice1 = Math.random() * 6 + 1;
double dice2 = Math.random() * 6 + 1;
double total = (dice1 + dice2);
System.out.println("Dice 1: " + x.format(dice1) + " Dice 2: " + x.format(dice2) + " Total: " + x.format(total));
}
I think its because the int total is set to 0 and isn't getting the total from the loop but how can i fix this?
Your while loop logic is not correct. The total will always not be 7 or not be 11. You want "and" instead, using &&. Change
while (total != 7 || total != 11) {
to
while (total != 7 && total != 11) {
Also, I don't know of any dice that yield non-integers, so I would cast the results to int and declare dice1, dice2, and total as ints.
It's because you shadow total and you need to test logical and (not or). I would also prefer to use Random and nextInt(int) like
int total = 0; // <-- don't shadow me.
Random rand = new Random();
while (total != 7 && total != 11) {
int dice1 = rand.nextInt(6) + 1; // <-- using rand.
int dice2 = rand.nextInt(6) + 1;
total = (dice1 + dice2); // <-- no double.
System.out.printf("Dice 1: %d Dice 2: %d Total: %d%n", dice1, dice2, total);
}
You need an AND instead of an OR. And try it with int:
int total = 0;
while (total != 7 && total != 11) {
Random rand = new Random();
int dice1 = rand.nextInt((6 - 1) + 1) + 1;
int dice2 = rand.nextInt((6 - 1) + 1) + 1;
total = (dice1 + dice2);
System.out.println("Dice 1: " + dice1 + " Dice 2: " +dice2 + " Total: " + total);

Getting same random numbers every time

I'm trying to write a program that generates a random school timetable with random positions and a random amount of hours for each teacher, but with a fixed total amount of time per day. For now the program is written to work with two days, and I'm encountering an issue: the random-generated values for the amount of time between the two days are the same:
import java.util.Random;
public class randomTimetable {
public static void main(String[] args) {
String newLine = System.getProperty("line.separator");
System.out.println("For each day (x + y + ... n) >= 5 and" +newLine +"(x && y && ... n) <= 2" +newLine);
createTimetable();
}
private static void createTimetable() {
String x_g1 = "x";
String y_g1 = "y";
String z_g1 = "z";
String m_g1 = "m";
String[] arrayTimetablePosition1={x_g1, y_g1, z_g1, m_g1};
String newLine = System.getProperty("line.separator");
System.out.println("Work In Progress" +newLine +"Total subjects = 5" +newLine +"Day 1");
Random rand = new Random();
int min = 0;
int max = 2;
int x1 = rand.nextInt(max - min + 1) + min;
int y1 = rand.nextInt(max - min + 1) + min;
int z1 = rand.nextInt(max - min + 1) + min;
int m1 = rand.nextInt(max - min + 1) + min;
while((x1 + y1 + z1 + m1) != 5) {
x1 = rand.nextInt(max - min + 1) + min;
y1 = rand.nextInt(max - min + 1) + min;
z1 = rand.nextInt(max - min + 1) + min;
m1 = rand.nextInt(max - min + 1) + min;
}
System.out.println("x1 = " +x1 +newLine +"y1 = " +y1 +newLine +"z1 = " +z1 +newLine +"m1 = " +m1 +newLine);
System.out.println("Total subjects = 5" +newLine +"Day 2");
int x2 = rand.nextInt(max - min + 1) + min;
int y2 = rand.nextInt(max - min + 1) + min;
int z2 = rand.nextInt(max - min + 1) + min;
int m2 = rand.nextInt(max - min + 1) + min;
while((x2 + y2 + z2 + m2) != 5 && (x1 == x2 || y1 == y2 || z1 == z2 || m1 == m2)) {
x2 = rand.nextInt(max - min + 1) + min;
y2 = rand.nextInt(max - min + 1) + min;
z2 = rand.nextInt(max - min + 1) + min;
m2 = rand.nextInt(max - min + 1) + min;
}
System.out.println("x2 = " +x1 +newLine +"y2 = " +y1 +newLine +"z2 = " +z1 +newLine +"m2 = " +m1 +newLine);
}
}
specifically the value of x1 is the same of x2, the one of y1 is the same of y2 and so on.
You're Random construction is fine - you're using the default constructor, which automatically uses the time as a seed:
public Random() { this(System.currentTimeMillis()); }
But you have a copy/paste error in your last debug-print statement. You're label says x2, but you're printing x1, etc.
System.out.println("x2 = " +x1 +newLine +"y2 = " +y1 +newLine +"z2 = " +z1 +newLine +"m2 = " +m1 +newLine);
I cannot see any initialization of the pseudorandom number generator.
You need to set the seed of the PRNG.
Looks like you are using the same seed. see:
http://docs.oracle.com/javase/6/docs/api/java/util/Random.html
LOL, it's a copy-paste error
last line should read
System.out.println("x2 = " +x2 +newLine +"y2 = " +y2 +newLine +"z2 = " +z2 +newLine +"m2 = " +m2 +newLine);
but it sounds like a classic random-seed problem. That's pretty funny.

Categories