0

I need to create a program that prints 6 numbers between 1 and 42 at random where no 2 numbers are the same. The user must also insert 6 numbers. If any number is the same as the one randomly selected by the computer, the computer must print it. If not, the computer prints you are such a loser. Now, the problem is I'm not sure about how to make sure that no 2 randomly selected numbers are the same. The program should also ask for a different number if a number less than 1, greater than 42, or equal to a previous number inserted, and scan it which I am also not able to do. (user cannot enter 2 identical numbers)

import java.util.Scanner;
import java.util.Random;

public class LotoMachine {

public static void main(String[] args) {

    System.out.println("Please enter 6 numbers between 1 and 42.");
    Scanner scan = new Scanner(System.in);

    int[] marks = new int[6];
    Random ran = new Random();
    int[] x = new int[6];
    boolean winner = false;

    for (int i = 0; i < 6; i++) {
        marks[i] = scan.nextInt();
        while (marks[i] > 42) {
            System.out.println(marks[i] + " is out of range. Please pick a number that is less than 43.");
            marks[i] = scan.nextInt();
            i=0;

        }
        while (marks[i] < 1) {
            System.out.println(marks[i] + " is out of range. Please pick a number that is greater than 0.");
            marks[i] = scan.nextInt();
            i=0;
        }
        while (marks[i] == marks[i] - 1) {
            System.out.println("You have already chosen " + marks[i] + "Please pick a different number.");
            marks[i] = scan.nextInt();
            i=0;

        }
    }
    for (int j = 0; j < 6; j++) {
        x[j] = ran.nextInt(42) + 1;
        for (int y = 0; y < j; y++) {
            if (x[j] == x[y]) {
                x[j] = ran.nextInt(42) + 1;
                j = 0;

            }
        }
    }
    System.out.print("You chose");
    for (int m = 0; m < 6; m++) {
        System.out.print(" " + marks[m]);
    }
    System.out.println(" ");
    System.out.print("The random numbers are");
    for (int m = 0; m < 6; m++) {
        System.out.print(" " + x[m]);
    }
    System.out.println(" ");
    System.out.print("The number(s) that matched are");
    for (int i = 0; i < 6; i++) {
        for (int j = 0; j < 6; j++) {
            if (marks[i] == x[j]) {
                winner = true;
                System.out.print(" " + marks[i]);
            }
        }
    }
    if (winner != true) {
        System.out.println("You are such a loser");

    }
}

}

  • 7
    Random numbers without sameness are normally generated by *shuffling* the possible population and reading as many values as you need from the resulting container. – Bathsheba May 09 '17 at 14:52
  • Possible duplicate of the exact same homework question: http://stackoverflow.com/questions/43872668/building-a-lotto-machine-using-java-program-doesnt-function-if-same-number-is – hamena314 May 09 '17 at 15:01
  • I added to the code –  May 09 '17 at 16:49

2 Answers2

2

You can use a Set to store the values and ask for the size after the addition. Whenever you want to deal with collections of objects which should not be repeated, a Set is a good way to go, since it allows no duplication. Something like this:

Set<Integer> numbers = new HashSet<Integer>();

random code goes here...

int size = numbers.size();
numbers.add(newValue);
if(numbers.size() == size){
    number needs to be created again...
}
NachoGobet
  • 31
  • 5
  • Problem with this approach is, if - for any reason - your random generator always returns the same value, you run into a an endless loop. – Gerald Mücke May 09 '17 at 15:01
  • This method can work well if the number of number required is small and the population is large. – Bathsheba May 09 '17 at 15:02
  • @GeraldMücke well in that case it's the random generator that is broken and needs to be fixed. – NachoGobet May 09 '17 at 15:05
  • @Bathsheba can you explain why the input size affects it? the complexity of the contains method is 1 and is not dependent on input size. – NachoGobet May 09 '17 at 15:07
  • However unlikely, a random generator may return always the same number without being broken – Gerald Mücke May 09 '17 at 15:34
  • @GeraldMücke Do you know how a random number generator works? It uses seeds, you generally use current system time. The probabilities of what you're suggesting happening are beyond ludicrous. Plus if the random generator generates always the same number, then the whole program will run indefinitely, not only my algorithm. – NachoGobet May 10 '17 at 09:40
  • I know that the possibility is extremely low, practically 0, but it's not guaranteed it's 0. From a mathemetical standpoint drawing 6 from 42 are 6 dependent events (conditional probability), while drawing 6 times from 42 are 6 independent events (unconditional probalitity), meaning each times you have same chance of drawing the same number, the probability of drawing 1000x times the same number is (1/42)^1000 which is not 0 – Gerald Mücke May 10 '17 at 10:38
  • @GeraldMücke do we at least agree that if the generator returns always the same number then the whole program will run indefinitely, no matter what your algorithm is? – NachoGobet May 10 '17 at 14:51
  • no it won't if you use the right algorithm, if you remove the element you have drawn from the set of drawable elements before you draw the next, you can draw exactly 6, even if your random produces constant values (see the algorithm in my answer). And I'm not saying your algorithm won't work, but it might fail (maybe in 1000 years :) – Gerald Mücke May 10 '17 at 15:04
0

Basically, there are two ways to draw 6 from 42.

The first is to draw continuously until you have 6 unique numbers. Each draw has the same probabilty (1/42) to draw a particular number. Although the likelyhood of the case that you always draw the same number is low, it is not 0. So from a statistical point of view, this is not correct. In Java you could do this is

Random rand = new Random();
List<Integer> randomNumbers = Stream.generate(() -> rand.nextInt(42))
                                    .distinct()
                                    .limit(6)
                                    .collect(toList());

What you actually want to have, is to draw 1 of 42, 1 of 41, 1 of 40 ... One approach to do this is to generate a list of all possible number (1..42), draw one, remove it from the list, draw another etc. In Java that would be

final List<Integer> numbers = IntStream.rangeClosed(1, 42)
                                       .boxed()
                                       .collect(toList());
final List<Integer> randomNumbers2 = Stream.generate(() -> rand.nextInt(numbers.size()))
                                           .limit(6)
                                           .map(i -> numbers.remove((int)i))
                                           .collect(toList());

Finally reading input until you have a valid number is easily done with a do-while loop

Scanner scanner = new Scanner(System.in);
int number;
do{
  number = scanner.nextInt();
} while(number < 0 && number > 42);

if(randomNumbers2.contains(number)){
  System.out.println("Winner");
} else {
  System.out.println("Looser");
}
Gerald Mücke
  • 9,470
  • 1
  • 40
  • 62