I'm making a program of the Card game War and I need the cards to not reappear so I used an Array list. I'm having trouble with this array list as it's supposed to be random and remove the number, but I get the error IndexOutOfBoundsException: Index 0, Size 0
List<Integer> values = new ArrayList<Integer>();
Random random = new Random();
Integer rand = random.nextInt(values.size()+1);
Integer cardId = values.get(rand);
values.remove(rand);
First add your Card(s) to your values List (e.g. probably not Integer).
What I'm saying is this, you need a deck of cards before you can play.
Your list is empty and you're
1) Trying to retrieve a value
2) Trying to remove a value
Which throws an error because the list is empty.
Sidenote: you can define rand and cardId as int, instead of Integer. Autoboxing/unboxing will take care of that for you.
Add values to your list and it will work as expected (and if you change random.nextInt(values.size()+1) to random.nextInt(values.size())).
You get this error because you try to access index 0 of an empty array, as it says. You cannot do this.
Your code has multiple issues.
You are not actually storing anything in values.
The acceptable range of indexes for .get() is 0 to size-1. The return range of random.nextInt(size+1) is 0 to size. This can produce out of range index values. Array indexes start at 0.
Provide the code for the values in the array...Or add values in the array.
You need to first give the List values before you can get values
List<Integer> values = new ArrayList<Integer>();
Random random = new Random();
Integer rand = random.nextInt(values.size()+1);
Try this to put values
for (int i = 1; i <= 52; i++){
values.add(i);
}
Integer rand = random.nextInt(values.size() + 1);
Related
I want to ask how to generate a random number in java , i know it is done by random.nextint() but i want to check if the number is not what i wanted then it should be rejected and a new random number should be generated .
I want something like this :
Integer[] in = {1,2,3,4,5};
int a = new Random().nextInt(10);
for(int i=0;i<in.length ;i++)
if(a==in[i])
//new random number
if the number is present in the above array (in) then new random number should be generated
Just put it in a do-while loop:
int a;
do {
a = new Random().nextInt(10);
} while (Arrays.asList(in).contains(a));
I would avoid not generating a number you didn't want in the first place.
You can do either
int a = random.nextInt(5);
if (a > 0) a += 5;
or use a selection
int[] valid = { 0, 6, 7, 8, 9 }; // 0 to 9 but not 1,2,3,4,5
int a = valid[random.nextInt(valid.length)];
Simply call the method again. That is, if the number generated fits the if criteria then call a = new Random().nextInt(10);
Or, if your for loop ever regenerates a random number, you could just have the if statement do nothing ex: if(xyz){}; which of course would be pointless, and I think the original solution is probably what you seek.
To avoid any loops and retrying, try this:
int [] in = {1,2,3,4,5};
// generate integers from 0 up to the size of your array of allowed numbers:
int index = new Random().nextInt(in.length);
int a = in[index]; // use the random integer as index for your array of allowed numbers
I am trying to make it so I can write data to a ArrayList to track random integers and then I will have a previous button that will go back to the last result (This is just testing that code this is not the full code for the project) I am getting an error when trying to take the int arraySize and subtract it by 1 and reprint the data. Any idea why this is happening or how another way to accomplish the task.
int lenth = 10;
ArrayList<Integer> list = new ArrayList<Integer>();
int arraySize = list.size();
Random random = new Random();
int newRandom = random.nextInt(lenth);
list.add(newRandom);
newRandom = random.nextInt(lenth);
list.add(newRandom);
System.out.println(list.get(arraySize));
arraySize--;
System.out.println(list.get(arraySize));
Also here is the error I am getting:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at test.C_MainActivity.main(C_MainActivity.java:22)
When you assign one primitive (such as an int) to another, this copies the value to the new variable. For objects, this works a bit differently in that these variables will point to the same object.
int arraySize = list.size();
So the above line will just set arraySize to the current size of the list, arraySize will not change as the list size changes. Since you do this when the list is empty, it will be and remain 0 and you'll try to get the elements at indices 0 and 0-1 = -1, which is where your exception comes in.
You should just set it after you've inserted all elements instead.
Note that indexing in Java starts at 0, so the last element will already be at list.size() - 1, not list.size().
You are setting arraySize before anything has been added to the list. The value of arraySize will always be 0 because you only set it at the beginning. When you call arraySize--, arraySize is now -1 and when you call list.get(arraySize), you will get an index out of bound exception as you are asking for index -1.
It seems like your goal is to enqueue values in a collection and then dequeue them. A LinkedList, for example, would be more appropriate with its push() and pop() methods.
Anyway you should not keep track of the ArrayList's size through an external variable. Such data is already provided for you inside ArrayList so you just have to query the list to know its size.
Suppose I wanted to generate random numbers taken from ArrayList:(1,2,3,4,5,6,7,8,9,10)
A Random Generator produces 5.
List gets updated- AL:(1,2,3,4,6,7,8,9,10)
Next Random Number cannot be 5.
I am writing a program that generates random numbers from a arraylist and once it generates the random number the list removes that number and the next random generated digit cannot be that number.
ArrayList<Integer> numsLeft = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5,6,7,8,9,10));
Random randomGenerator = new Random();
int number = 0;
String cont;
do
{
number = randomGenerator.nextInt(numsLeft.size());
numsLeft.remove(number);
System.out.println (number + " continue (y/n)");
cont = (stdin.readLine());
}
while (cont.equalsIgnoreCase("y"));
But the only thing I can do here is lower the size...
http://docs.oracle.com/javase/7/docs/api/java/util/Random.html
The easier approach is to simply shuffle your list then use the numbers in the shuffled order:
List<Integer> nums = new ArrayList<Integer>();
for (int i = 1; i < 11; i++)
nums.add(i);
Collections.shuffle(nums);
Now they are in random order, just use them one by one:
for (Integer i : nums) {
// use i
}
You could make an array of the available numbers. Then, the random number generator gives you the position in that array for the number that you want.
Probably a linked list or something would be more efficient, but the concept is the same.
So, with your example, you'd pull 5 the first time. The second time, you'd have this in your list:
1, 2, 3, 4, 6, 7, 8, 9
If your random number was 5 again, the fifth position is 6. Pop the six out, shift 7, 8, 9 over one, and decrement your random number generator to be 1-8 instead of 1-9. continue on.
of course, looking at your code, it looks like that is what you are trying to do already.
What seems to be the issue with your code? What results are you getting?
number = randomGenerator.nextInt(numsLeft.size());
numsLeft.remove(number);
You are now printing the random index that you are generating, not the number that was removed from the list. Is that what you wanted? I think you really meant this:
int index = randomGenerator.nextInt(numsLeft.size());
number = numsLeft.remove(index);
You could also do this using by randomly shuffling the list and then just going through it:
List<Integer> numsLeft = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5,6,7,8,9,10));
// Shuffle the list randomly
Collections.shuffle(numsLeft);
do {
// Remove the first number each time
int number = numsLeft.remove(0);
System.out.println (number + " continue (y/n)");
cont = (stdin.readLine());
} while (cont.equalsIgnoreCase("y"));
Why don't you create a hash map to take care of this. So your hash map can contain something like
Map[(1,1), (2,2), (3,3), ...] or Map[(1,true), (2,true), (3,true), ...]
So if you generate a number, then you can do something like:
String value = map.get(key); or boolean present = map.get(key);
if(value != null) or if(value == present)
map.remove(key), or you can even update the data and instead of removing the key you can update it and add the word removed or a boolean as previously suggested. But this way you can keep track of all the entries and removals in your map for each of the key values which would be your list of numbers.
remove can be pretty expensive operation when list is long. Shuffle is too - especially if you only need a few numbers. Here is another algorithm (it is famous but I can't find the source right now).
put your N (ordered) numbers in a list
Choose a random number m between 0 and N-1
Pick the element at location m. This is your unique random number
SWAP element m with the LAST element in the array
Decrement N by 1
Go to step 2
You "set aside" the numbers you have used in step 4 - but
Unlike shuffle, your initialization is fast
Unlike remove, your remove operation only takes moving one element (instead of, on average, N/2)
Unlike the "pick one and reject if you saw it before", your efficiency of picking a "new" number doesn't decrease as the number of elements picked increases.
I have created a method to randomize the list:
public <T> List<T> randomize(List<T> list) {
LinkedList<T> randomizedList = new LinkedList<>();
Random random = new Random(list.size());
for (int i = random.nextInt(); i < list.size(); i++) {
randomizedList.add(list.get(i));
}
return randomizedList;
}
The list that I am passing to this method contains for e.g. five elements. When I am creating Random random = new Random(list.size()); I expect so when I call random.nextInt() what it will return me the random integer which will be an index of the list element.
But when I call random.nextInt(); instead of returning the number from the interval [0, 4] (which I expect to be returned) it returns me the value of for e.g.: -349120689. Which gives me an java.lang.IndexOutOfBoundsException: Index: -349120689, Size: 5.
Why is this happening and how to solve this?
new Random(list.size()); this sets the seed of the Random number generator to list.size(); I suggest changing to new Random() (which will give you a seed based on the current time of the system). Preferably though, you'd want to reuse the same Random object at all times.
random.nextInt(); here is where you'd want to put random.nextInt(list.size()); which will give you a number from 0 to list.size() - 1.
Even with the above changes, your code would just give you a sublist of the list starting at a random index and going until the end. Use Collections.shuffle(list) instead.
To do a real shuffling, you would need to "remember" which elements
you have inserted or not. In pseudo-code, you could do the
following:
Copy the original list to a new one, let's call it "orig"
Create a new, empty, list, let's call it "result"
As long as the orig list has elements, get an element at random index and add it to the result list. Remove the chosen element from orig list.
Return result list.
I expect so when I call random.nextInt() what it will return me the random integer which will be an index of the list element.
You've misunderstood the purpose of the Random(long) constructor. The purpose of that constructor is to specify a seed for the list. You don't want to do this - it would mean that every collection of size 5 is always shuffled the same way.
You specify the range on each call to nextInt. So if you want a random number between 0 (inclusive) and max (exclusive) you just use:
int value = random.nextInt(max);
However, it would be much better just to use Collections.shuffle instead of writing your own code to do this - assuming you really want a shuffle (which isn't what your current approach would give you anyway - even after fixing the nextInt call, you'd end up
with basically a sublist, because nextInt() is only called once. So if the first call to nextInt() returns 2 (in a list of 5) you'd end up returning a new list containing the final 3 elements. I strongly suspect that's not what you were trying to do.
As a side-note, when you want to know why an API isn't behaving the way you expect it to, read the documentation. The documentation of the Random(long) constructor and Random.nextInt() are pretty clearly not the behaviour you were expecting.
use this
public <T> List<T> randomize(List<T> list) {
LinkedList<T> randomizedList = new LinkedList<>();
Random random = new Random();
for (int i = random.nextInt(list.size()); i < list.size(); i++) {
randomizedList.add(list.get(i));
}
return randomizedList;
}
The argument to the Random constructor is a random seed, not the maximum of what it returns.
Pass the maximum number to nextInt() instead.
You're confusing the argument to nextInt(n) (upper bound for the randomization) with the argument to the constructor (random seed). You shoudl use nextInt(list.size), and probably, initialize the Random object using new Random().
Hi so I'm doing an assignment but I've kind of fallen flat on the concept of 2D arrays. I'm writing a method body that randomly selects an element in a 2D array. However, I'm not completely sure when of how to approach the problem.
I was thinking of using a random number generator to select a random element. Although what I need first is for the whole length of the box to be filled first with a value. In this case, the dimensions of the 2D array box are 20x20 and the value is zero. So I'd want the 2D array to be complete filled with zeroes. Although if I used a random number generator, is there a chance that an element which was randomly selected by the generator could possibly be used again before the entire box dimensions are filled first with zero?
Sorry for the long block of text. Basically what I'm asking is if there is a way to use random number generator to still randomly generate numbers but not repeat any its used previously.
One option is to use Collections.shuffle(allCells).
Another option is to use the following algorithm, by keeping track of remaining unused cells:
1. Find a random number from 0 to size of the set - 1 .
2. Remove number at position `randomNumber` from the set.
3. Go to 1.
I would go this way:
int [][] myArray = new int[4][5]; //Any size and type
int totalEmenent = myArray.length *myArray[0].length;
int indexToSelect = (int)(Math.random()*totalEmenent);
int xIndex = (int)indexToSelect/myArray.length;
int yIndex = indexToSelect%myArray.length;
int selectElement = myArray[xIndex][yIndex];
If you wish to select unique index each time:
int [][] myArray = new int[4][5]; //Any size and type
int totalEmenent = myArray.length *myArray[0].length;
String selectedIndex = "";
int numberOfSelect = 10; //Any number< totalEmenent
for(int indx=0; indx< numberOfSelect; indx++){
int indexToSelect = (int)(Math.random()*totalEmenent);
//generate random until its unique
while(selectedIndex.indexOf(String.valueOf(indexToSelect))> 0){
indexToSelect = (int)(Math.random()*totalEmenent);
}
selectedIndex = selectedIndex+indexToSelect;
int xIndex = (int)indexToSelect/myArray.length;
int yIndex = indexToSelect%myArray.length;
int selectElement = myArray[xIndex][yIndex];
}
From what I read above... you want to fill a 20x20 2D array with 0's, but you want to do it by selecting a random location in the array each time, and you don't want to "re-fill" a slot.
The fastest way to do this is to create an array with all the possible locations (in this case, that's 0..399, if you figure that the value/20 = the first index, and value%20 = the 2nd index, e.g. 125 = array[125/20][125%20] or array[6][5], see?)
so, first, fill this array locations[400] with the values 0..399.
int [][] box = new int[20][20];
int [] locations = new int[400];
for ( int i = 0; i < 400; i++ ) locations[i] = i;
Then, starting with a cap of 399, generate a random number loc from 0 to cap, and use the locations[loc] as your current index to fill with a 0, then swap the locations[loc] with locations[cap], decrease cap by 1, and continue. By the time cap reaches 0, you'll have used all the locations.
int cap = 399;
Random rand = new Random();
while ( cap >= 0 ) {
int rnd = rand.nextInt(cap+1);
int loc = locations[ rnd ];
box[loc%20][loc/20] = 0; // Here's where we set the value 0 into the 2D array
// now swap the location selected with the value at the "end" of the current list.
// hmm, forget the swapping, let's just bring that value in from the end.
locations[rnd] = locations[cap];
cap--; // "shrink" the current list, eliminating the value we just put at the end from consideration.
}
That should do it. You should be able to see that this will never pick the same value out of the "locations" array, since the swap at the end of the loop puts that locations value outside the boundary of index 0 to cap. The next time through the loop, it's impossible to select that value again (or any other value that's already used).
While populating your array, you can have an arraylist to add the index of each cell(say i,j), and then generate random number
Arraylist<int[]> ar=new Arraylist();
//inside loop for populating array
yourArray[i][j]=whatever;
ar.add({i,j});
//loop ends
int index=new Random().nextInt(ar.size());
int[] arrayIndex=ar.get(index);
ar.remove(index);
row=arrayIndex[0];
column=arrayIndex[1];
(Type)randomElement=yourArray[row][column];