I want to make a quiz with a switch-case statement. Before entering it I generate a random number between 1 and for example 10. Then there are 10 cases, one for each number. In each of them there is a question, meaning, that the program displays a random question at the beginning. When the question is answered correctly i want the program to pick a random question again by generating a number but not the one who was already picked. How do i do that?
You don't have to use switch for this. Try the following code.
public void play() {
range = new ArrayList<>();
range.addAll(IntStream.rangeClosed(0, questions.size() - 1).boxed().collect(Collectors.toList()));
//Assuming 'questions' is an array list of questions
int index = getQnNumber(); // use this to get a valid question index which is not yet asked
if(index == -1) //means game over
System.out.println("Completed");
else
askQuestion(index);
}
private int getQnNumber() {
int size = range.size();
if(size < 1)
return -1;
Random r = new Random();
int index = r.nextInt(size);
int questionNumber = range.get(index);
range.remove(index);
return questionNumber;
}
You can maintain an ArrayList of the numbers that have been generated already. On every new random generation,
if(!myList.contains(newRandom)){
return newRandom;
}else{
//generate a new random and check
}
Related
I have a problem for an online course I am doing. The question is:
Given an Integer x, write a program which generates random numbers between x and 0 until each number in this range has been generated at least once. Once all numbers in this range have been generated, the program should display the numbers which were generated.
I have written a program which I thought would solve this but am having problems with the checking if a number is in the range. Here is my code so far:
public static void main(String[] args) {
Random generator = new Random();
ArrayList<Integer> range = new ArrayList<Integer>();
ArrayList<Integer> generated = new ArrayList<Integer>();
int x = 10;
int count = 0;
for(int i = 0; i<x+1; i++){
range.add(i);
}
while(range.isEmpty() != true){
int temp = generator.nextInt(x-1);
count++;
generated.add(temp);
if(range.contains(temp)){
range.remove(temp);
}
}
}
}
My idea was to first create two arraylists. The first would hold all numbers between 0 and the given x. The second would contain the random numbers generated. I then fill the range arraylist with the range between 0 and x. My While loop then checks this range list to see if it is empty. If not, it generates a random number, adds it to my second arraylist. I then check if this number is in the range arraylist - if it is it removes it and carries on. The problem I am having is it is running into IndexOutOfBoundsException after a few goes. I think this is because I am removing the generated numbers from the arraylist. Can anyone help me with fixing this
EDIT: I cant use any collections or other APIs. This part of the course is mainly about using Arrays and loops etc, not advanced Java stuff.
remove is an overloaded method, there is remove(int) which removes the item at the index specified and there is remove(T) which removes the first object int the list that is equal to the argument you passed in
since you passed an int to the method not an Integer, the first method is chosen
the simpliest modification to your code is replacing range.remove(temp); with range.remove(range.indexOf(temp)); or range.remove((Integer)temp)
also you have to call generator.nextInt(x+1); or else the program will be stuck in an infinite loop
You can just replace range.remove(temp); with range.removeIf(t -> t == temp);
Random generator = new Random();
ArrayList<Integer> range = new ArrayList<Integer>();
ArrayList<Integer> generated = new ArrayList<Integer>();
int x = 10;
int count = 0;
for(int i = 0; i<x+1; i++){
range.add(i);
}
while(range.isEmpty() != true){
int temp = generator.nextInt(x-1);
count++;
generated.add(temp);
if(range.contains(temp)){
range.removeIf(t -> t == temp);
}
}
OR You can use Iterator to remove from the List
for (Iterator<Integer> it = range.iterator(); it.hasNext(); ) {
Integer obj= it.next();
if (obj == temp) {
// Remove the current element from the iterator and the list.
it.remove();
break;
}
}
One more issue in your logic
int temp = generator.nextInt(x-1); The random number you are generating doesn't contain all the numbers. It should be int temp = generator.nextInt(x+2);
Hope the below will meet your requirement.
Random random = new Random();
int x = 3;
List<Integer> range = new ArrayList<>();
for(int i = 0; i <x+1; i++) {
range.add(i);
}
List<Integer> list = new ArrayList<>();
while (!list.containsAll(range)) {
list.add(random.nextInt(x + 1));
}
System.out.println(list);
This question already has answers here:
Creating random numbers with no duplicates
(20 answers)
Closed 8 years ago.
I'm working on building one of my fist apps and I'm building a Sudoku mobile game. I've built the random number generator I just cant figure out how to write it so that it only generates numbers between 1-9 (not zero) and each of numbers are only generated once. Here is what I have so far:
package randomNumber;
import java.util.Random;
public class OneToNine {
public static final void main(String... aArgs) {
log ("generating random integers in range 1-9");
Random randomGenerator = new Random();
for (int idx = 1; idx <= 9; ++idx) {
int randomInt = randomGenerator.nextInt(9);
log ("Generated : " + randomInt);
}
log("Done. ");
}
private static void log (String aMessage) {
System.out.println(aMessage);
}
}
Rather than worry about generating the numbers in a random order, you should adjust your approach to shuffling the numbers. You know you will have the numbers 1-9 so do something like this:
public ArrayList<Integer> getRandomOrderedNums(){
ArrayList<Integer> numbers = new ArrayList<Integer>();
for(Integer i = 1; i < 10; i++){
numbers.add(i);
}
Collections.shuffle(numbers);
}
For your second part, to see if the numbers are repeated, you can easily use a data structure such as a HashSet, which is the most efficient to check for repeated values. Let me know if you're not fully comfortable with them. Using the hashset, you can come up with a random number, and check if the set contains this number, and if it does, try again.
With regards to the random number, you can just do randomGenerator.nextInt(9) + 1 so it'll always be from 1-9 (inclusive).
You might want to use a function like this:
public static int getRandInt(int max, int min) {
return new Random().nextInt((max - min) + 1) + min;
}
The following code shows 4 int variables:
int xy1 = 724329;
int xy2 = 714385;
int xy3 = 715440;
int xy4 = 696492;
I'm pretending to code an app that, by opening it, shows one of those numbers (NOT numbers between them) on java console, randomly. I know that Math.Random class can be used to solve these kind of issues, but I don't know what is the proper way to do so.
So, thanks.
Well it sounds like you just want a collection of possible values, and an index between 0 and 3 inclusive:
int[] values = { 724329, 714385, 715440, 696492 };
Random random = new Random(); // Ideally initialize once for the entire app
int index = random.nextInt(4);
int value = values[index];
Place them into an array and use Random to select a number between 0-3 and use it as a key to select the value from the array.
Try this one.
This line
r.nextInt(nums.length)
selects an integer from 0 to nums.length-1.
Then I print out the randomly selected number from the nums array.
I repeat this 20 times just for demonstration purposes.
import java.util.Random;
public class Test015 {
public static void main(String[] args) {
int[] nums = {724329, 714385, 715440, 696492};
Random r = new Random();
for (int i=0; i<20; i++){
int index = r.nextInt(nums.length);
System.out.println("Number randomly chosen: " + nums[index]);
}
}
}
This question already has answers here:
Non repeating random numbers
(2 answers)
Closed 8 years ago.
When using the random utility in java, you get some numbers like this: 1271, 34556, 177, etc... What is the simplest way to make it so the digits don't repeat?
You could shuffle the array [1,2,3,4,5,6,7,8,9] and read that as a number.
If you don't want to fix the number of digits, or allow a non-leading zero, it gets more complicated (if you care about some sort of equal distribution).
You could initialize a List with the digits 0-9. Then randomize this list and poll a random amount of elements (between 1 and 9) from this list. Concatenate the digits and you have your number with non-repeating digits.
How about creating a loop that checks if the generated random number meets your requirements.
final Random rnd = new Random();
int n;
do {
n = rnd.nextInt(1000);
} while(containsRepeatingDigits(n));
containsRepeatingDigits can look like this:
boolean containsRepeatingDigits(final int n) {
final boolean digits[] = new boolean[10];
for(char c : String.valueOf(n).toCharArray()) {
final int i = c-'0';
if(digits[i])
return true;
digits[i] = true;
}
return false;
}
You could check if the random number has repeating digits and generate a new one if it does. It's written in C#, but you should be able to convert this to Java real easy.
private static Random rand = new Random();
public static int GenerateNumberNonRepeat()
{
int number;
do
{
number = rand.Next();
} while (IsRepeating(number));
return number;
}
public static bool IsRepeating(int number)
{
string textual = number.ToString();
for (int i = 0; i < textual.Length; i++)
{
for (int j = i + 1; j < textual.Length; j++)
{
if (textual[i] == textual[j])
return true;
}
}
return false;
}
Another way to generate those numbers is to generate arbitrary number, and in case that it contains repeating digits either generate a new one, or remove the repeating digits (by e.g. increment the number until there are no more repeating numbers).
In contrast to proposed shuffle/select approach this has the advantage, that you keep (more or less) the distribution of the original rng.
This code may help you
Set set = new HashSet<Integer>();
Random rand= new Random();
public int getNonRepeatingRandomNumber() {
int intV = rand.nextInt();
if(set.contains(intV)) {
return getNonRepeatingRandomNumber();
}
else {
set.add(intV);
return intV;
}
}
I need help with this part of my code. This part deals with generating 2 random numbers and using that random number to display a card in each of 2 label boxes simultaneously. The problem here is the random numbers are not getting generated properly and thus cards are not displayed properly (there is repetition, sometimes no display, etc)
Basics of my code:
Let us assume h, which is a variable from another part of the code, is any number between 1 and 53 (each number pertaining to a card). If the random number generated (non-repetition) matches the variable h the timer stops.
So its basically like having a deck of cards and dealing out the cards evenly to 2 people, but here the dealing stops once a number pertaining to a card (number) randomly taken is matched.
(l3,l4 are label names)
Global variables:
Random rng = new Random();
List<Integer> generated = new ArrayList<Integer>();
List<Integer> generated2 = new ArrayList<Integer>();
int l3count;
int l4count;
int Ulim = 53;
int Llim = 1;
int next;
int check;
int h;
int next2;
int Ulim2 = 53;
int Llim2 = 1;
final int p = h;
int delay2 = 1000;
final Timer timer2 = new Timer();
timer2.schedule(new TimerTask(){
public void run(){
for (int i = 1; i < 53; i++)
{
while(true)
{
next = rng.nextInt(Ulim) + Llim;
if (!(generated.contains(next)||generated.contains(next2)))
{
generated.add(next);
break;
}
next2 = rng.nextInt(Ulim2) + Llim2;
if (!(generated.contains(next)||generated.contains(next2)))
{
generated.add(next2);
break;
}
}
String a = Integer.toString(next);
String c = "C:\\Users\\mycompname\\Desktop\\deck\\"+a+".png";
String d = Integer.toString(next2);
String e = "C:\\Users\\mycompname\\Desktop\\deck\\"+d+".png";
for(int j = 1;j<=53;j++)
{
if(j%2==0)
{l3.setIcon(new ImageIcon(c));
}
else
{l4.setIcon(new ImageIcon(e));
}
}
if(next==p||next2==p)
check=10;
break;
}
if(check==10)
timer2.cancel();
timer2.purge();
}
},delay2, 1000);
Any help would be appreciated.
Thanks for your time.
You'd be better off dealing the cards out randomly.
Using the O(n) Knuth Shuffle you can pass along one card at a time, from one array to another.
Each new array you pass the card to will be a different persons' hand.
Keep adding 1 card at a time to each array from the deck array until each player has the number of cards your rules require.
Also, don't rely on random numbers being equal. See stupid-sort. Look for some other pattern instead. Like a random number of cards % cards_left you should stop giving out cards.
Update with code-sample, as per request:
public static void shuffle (int[] array) {
for(int n = array.length; (n > 1);) {
int k = gen.nextInt(n--);
int temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
The obvious problem is that Random.nextInt generates a number 0 (inclusive) and n (exclusive). So when you pass in a limit of 53, you're generating values between 0 and 52 — that's 53 possible values, and there aren't that many cards. So change the upper limit to 52.
Also, as other answers note, the reason you're getting collisions (dealing the same card to multiple hands), etc. is that you don't want to randomly select the cards. You actually want to randomly shuffle the deck.
Try using a shuffle algorithm instead.