I'm trying to write a simple game where an enemy chases the player on a grid. I'm using the simple algorithm for pathfinding from the Wikipedia page on pathfinding. This involves creating two lists with each list item containing 3 integers. Here's test code I'm trying out to build and display such a list.
When I run the following code, it prints out the same numbers for each array in the ArrayList. Why does it do this?
public class ListTest {
public static void main(String[] args) {
ArrayList<Integer[]> list = new ArrayList<Integer[]>();
Integer[] point = new Integer[3];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 3; j++) {
point[j] = (int)(Math.random() * 10);
}
//Doesn't this line add filled Integer[] point to the
//end of ArrayList list?
list.add(point);
//Added this line to confirm that Integer[] point is actually
//being filled with 3 random ints.
System.out.println(point[0] + "," + point[1] + "," + point[2]);
}
System.out.println();
//My current understanding is that this section should step through
//ArrayList list and retrieve each Integer[] point added above. It runs, but only
//the values of the last Integer[] point from above are displayed 10 times.
Iterator it = list.iterator();
while (it.hasNext()) {
point = (Integer[])it.next();
for (int i = 0; i < 3; i++) {
System.out.print(point[i] + ",");
}
System.out.println();
}
}
}
First of all, several of the other answers are misleading and/or incorrect. Note that an array is an object. So you can use them as elements in a list, no matter whether the arrays themselves contain primitive types or object references.
Next, declaring a variable as List<int[]> list is preferred over declaring it as ArrayList<int[]>. This allows you to easily change the List to a LinkedList or some other implementation without breaking the rest of your code because it is guaranteed to use only methods available in the List interface. For more information, you should research "programming to the interface."
Now to answer your real question, which was only added as a comment. Let's look at a few lines of your code:
Integer[] point = new Integer[3];
This line creates an array of Integers, obviously.
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 3; j++) {
point[j] = (int)(Math.random() * 10);
}
//Doesn't this line add filled Integer[] point to the
//end of ArrayList list?
list.add(point);
//...
}
Here you assign values to the elements of the array and then add a reference to the array to your List. Each time the loop iterates, you assign new values to the same array and add another reference to the same array to the List. This means that the List has 10 references to the same array which has been repeatedly written over.
Iterator it = list.iterator();
while (it.hasNext()) {
point = (Integer[])it.next();
for (int i = 0; i < 3; i++) {
System.out.print(point[i] + ",");
}
System.out.println();
}
}
Now this loop prints out the same array 10 times. The values in the array are the last ones set at the end of the previous loop.
To fix the problem, you simply need to be sure to create 10 different arrays.
One last issue: If you declare it as Iterator<Integer[]> it (or Iterator<int[]> it), you do not need to cast the return value of it.next(). In fact this is preferred because it is type-safe.
Finally, I want to ask what the ints in each array represent? You might want to revisit your program design and create a class that holds these three ints, either as an array or as three member variables.
I would highly recommend to enclose the integer array of 3 numbers into a meaningful class, that would hold, display and control an array of 3 integers.
Then in your main, you can have an growing ArrayList of objects of that class.
You have an extra ) here:
element = (int[])it.next()); //with the extra parenthesis the code will not compile
should be:
element = (int[])it.next();
Besides the problem in the other answer, you cal it.next() two times, that cause the iterator move forward two times, obviously that's not what you want. The code like this:
element = (int[])it.next());
String el = (String)element;
But actually, I don't see you used el. Although it's legal, it seems meaningless.
Related
I have a small problem, I want to go through a list and compare two objects of the array. Each object has 3 elements, I use a StringTokenizer to be able to remove the separator, so each object has 3 elements. I would like to know how to make a method that gets the third element of each object and compare them. And if that element is less than another delete that element and the 2 before it.
I tried to make them with an iterator but I wouldn't know very well that it started from the 3 element and increased the position by 3.
Iterator<Integer> it = lisM.iterator();
int num;
while (it.hasNext()){
num = it.next();
System.out.println(num);
}
Is --> if, I was wrong to put it in the picture
This only answers part of your question. I could not understand the question completely, please edit it and I can edit my answer.
You should not remove items from a list whilst in a for loop, therefore you can, for example, create another boolean list with the same size divided by 3 and just fill it with true Booleans then set the position divided by 3 to false if you want to delete the three items. Then you can create a new list, iterate over the boolean list and add 3 "Objects" which are actually Strings (thanks #JB Nizet) at a time, every time the boolean list element is true. When it is false you just don't add the elements and by doing so you are practically deleting the two elements before that element together with that element.
You casted a String to an int, that does not work you have to parse the Strings.
I corrected some of your code and added the boolean list here:
ArrayList<String> lisM = new ArrayList<>(); // here I initialise the list as an array list with strings.
ArrayList<Boolean> booleanList = new ArrayList<>();
for (int i = 0; i < lisM.size() / 3; i++) {
booleanList.add(true);
}
for(int i = 3; i < lisM.size();i+=3) {
int m = Integer.parseInt(lisM.get(i)); // here I changed the casting to parsing and moved it out of the for loop, there is no need to initialize it again every single time since you do not change it in the second for loop.
for (int j = 6; j < lisM.size(); j += 6) {
int m1 = Integer.parseInt(lisM.get(j));// here I changed the casting to parsing again.
if (m > m1) { // this makes no sense here because you are going over all of the elements of the list and comparing them to all of them. But I kept it here for the sake of example.
booleanList.set(i/3,false);
}
// if you want to go over the whole list you will have to clear the list and start over again for every element.
}
}
and here is how you could create the new list without the elements you do not want:
ArrayList<String> newLisM = new ArrayList<>();
for (int i = 0; i <booleanList.size(); i++) {
if(booleanList.get(i))
for (int j = 0; j < 3; j++) {
newLisM.add(lisM.get(i+j));
}
}
for(int i = 0; i < bag.length; i++)
{
if(bag[i].equals(a))
{
tmp = bag[i];
bag[i] = bag[bag.length-1];
bag[bag.length-1] = tmp;
numElements--;
break;
}
}
The goal of this is to find an object in the array and then remove it? is it possible??
Changing the length of an array is not possible. Recall that array is a static data structure whose size is determined before hand. Increasing or decreasing is not supported in this data structure. The fact that one has to increase or decrease the size depending on the usecase means that they have picked up the wrong data structure. They should perhaps go with an ArrayList.
Anyway, coming back to your question, you can simulate the 'size decrease' by maintaining a variable which you let track the array index and decrease the size of this variable. This lets you give the impression of shrinking the array.
The code you have provided does the same. Note however, that you should be using this modified index to track the contents of your array.
for(int i = 0; i < bag.length; i++)
{
if(bag[i].equals(a))
{
tmp = bag[i];
bag[i] = bag[bag.length-1];
bag[bag.length-1] = tmp;
numElements--;
break;
}
}
Whenever a particular bag at a given index equals to the item under question i.e., 'a', we swap elements so that the current bag element to be removed moves to the last and also we reduce the size of our new index - numElements by 1 to simulate this.
If you have the full code with you, please consider adding the following snippet at the end of that program to understand this more:
// Simulation of the array shrinking.
for(int i = 0; i < numElements; i++)
{
System.out.println( bag[i] );
}
// Movement of uninteresting elements to the end of the array.
for(int i = 0; i < bag.length; i++)
{
System.out.println( bag[i] );
}
It's not possible to change the length of an array. You can overwrite the element you wish to remove with the last element of the array and then copy the first bag.length - 1 elements of your array to a new array whose length is bag.length - 1.
for(int i = 0; i < bag.length; i++) {
if(bag[i].equals(a)) {
bag[i] = bag[bag.length-1];
bag = Arrays.copyOf (bag, bag.length - 1);
break;
}
}
public static String[] removeElements(String[] input) {
List<String> result = new ArrayList<String>();
String deleteValue = "somevalue";
for(String item : input)
if(!deleteValue .equals(item))
result.add(item);
return result.toArray(input);
}
This is one method you can fit this into your program.
You cannot decrease the size of an array. okay no problem! you can create your own data structure which supports that right?
Now, create a class named say MyArray with functions like increaseLenght(int) and decreseLength(int). Try it if you want to, will be fun for sure..
You cannot reduce the size of an array. Arrays are fixed length. What you can do is have a variable that indicates how many entries of the array you are using. This is what you are doing with numElements. The standard class ArrayList is implemented like this. The data is kept in an array and a private field size is used. With an ArrayList, when you remove an element, all the elements to the right are shifted left. However I also like your idea.
I would suggest 2 changes.
Make the last element null instead. If you are removing the element, why does it still need to be in the array?
Use numElements - 1 rather than bag.length-1 as the array could be bigger.
With these changes it becomes:
for(int i = 0; i < bag.length; i++)
{
if(bag[i].equals(a))
{
bag[i] = bag[numElements-1];
bag[numElements-1] = null;
numElements--;
break;
}
}
I have created a list of 2D arrays containing randomly generated number values for different locations.
public static int Prices[][] = new int[Cities.length][ItemNames.length];
public static List<int[][]> CityPrices = new ArrayList<int[][]>();
public static void NewDay()
{
for(int i = 0; i<Cities.length; ++i)
{
Prices[i] = PriceGenerator.ReturnPricesForCity(i);
//This method returns an array of random integers
}
CityPrices.add(Prices);
}
But then later when I want to retrieve the price history for a specific item for the amount of days passed, it returns the same value for each day
int Prices[] = new int[GlobalVariables.CityPrices.size()];
String sTest = "";
for(int i = 0; i < Prices.length; ++i)
{
Prices[i] = GlobalVariables.CityPrices.get(i)[spinCity.getSelectedItemPosition()][spinItem.getSelectedItemPosition()];
sTest = sTest + Prices[i] + ",";
}
In this case, the values returned by sTest was : 6055,6055,6055,6055,6055, for five consecutive days.
If I would for instance add a day, the values would change to a range of a new number, which in this case was : 7294,7294,7294,7294,7294,7294,
Please show me what I am doing wrong, as I have been trying to figure this one out the past 4 days with no luck.
Every element in your CityPrices list is the same: in each case, you are adding the Prices two-dimensional array. Your loop modifies Prices[i], but it doesn't change Prices, which is still a reference to the same two-dimensional array right the way through.
I think you're imagining it will pass the contents of the array in its current state, but it doesn't: it passes a reference to the array to the .add() method, so any subsequent changes to the array will be reflected in the contents of CityPrices.
If at the end of your loop you try
CityPrices.get(0) == CityPrices.get(1)
you'll see it returns true.
In the assignment: Prices[i] = GlobalVariables.CityPrices.get(i)[spinCity.getSelectedItemPosition()][spinItem.getSelectedItemPosition()]; you are basically referencing an int[][] at the same index for both dimensions.
On top of that, the spinCity.getSelectedItemPosition() invocation might be returning the same index at every iteration of your loop, hence your identical values.
It's hard to assume anything further as you haven't posted the code for spinCity.
I'm taking a Java class in College. My instructor is actually a teacher for languages derived from C, so she can't figure out what's going on with this piece of code. I read on this page http://docs.oracle.com/javase/6/docs/api/java/util/List.html that I could use the syntax "list[].add(int index, element)" to add specific objects or calculations into specific indexes, which reduced the amount of coding needed. The program I'm looking to create is a random stat generator for D&D, for practice. The method giving the error is below:
//StatGenrator is used with ActionListener
private String StatGenerator ()
{
int finalStat;
String returnStat;
//Creates an empty list.
int[] nums={};
//Adds a random number from 1-6 to each list element.
for (int i; i > 4; i++)
nums[].add(i, dice.random(6)+1); //Marks 'add' with "error: class expected"
//Sorts the list by decending order, then drops the
//lowest number by adding the three highest numbers
//in the list.
Arrays.sort(nums);
finalStat = nums[1] + nums[2] + nums[3];
//Converts the integer into a string to set into a
//texbox.
returnStat = finalStat.toString();
return returnStat;
}
My end goal is to use some kind of sorted list or method of removing the lowest value in a set. The point of this method is to generate 4 random numbers from 1-6, then drop the lowest and add the three highest together. The final number is going to be the text of a textbox, so it is converted to a string and returned. The remainder of the code works correctly, I am only having trouble with this method.
If anyone has any ideas, I'm all ears. I've researched a bit and found something about using ArrayList to make a new List object, but I'm not sure on the syntax for it. As a final note, I tried looking for this syntax in another question, but I couldn't find it anywhere on stackoverflow. Apologies if I missed something, somewhere.
'int nums[]' is not a List, it's an array.
List<Integer> intList = new ArrayList<>();
creates a new ArrayList for example.
You can access Elements in the list directly with the following Syntax :
intList.get(0); // Get the first Element
You can sort Lists with the Collections class :
Collections.sort(intList);
Here are some informations about Collections in Java : http://docs.oracle.com/javase/tutorial/collections/
Arrays are fixed size, so you need to allocate space for all the slots at the start. Then to put numbers into the array assign to nums[i]. No add() method needed.
int[] nums = new int[4];
for (int i = 0; i < 4; i++)
nums[i] = dice.random(6) + 1;
Arrays.sort(nums);
finalStat = nums[1] + nums[2] + nums[3];
Alternatively, if you really want a dynamically-sized array, use an ArrayList. An ArrayList can grow and shrink.
List<Integer> nums = new ArrayList<Integer>();
for (int i = 0; i < 4; i++)
nums.add(dice.random(6) + 1);
Collections.sort(nums);
finalStat = nums.get(1) + nums.get(2) + nums.get(3);
Notice how different the syntax is due to ArrayList being a class rather than a built-in type.
nums[].add(i, dice.random(6)+1); //Marks 'add' with "error: class
expected"
You are trying to use add on an array. List is a dynamic array, but that doesn't mean that array == List. you should use List instead.
List<Integer> nums=new ArrayList<Integer>();
//Adds a random number from 1-6 to each list element.
for (int i; i > 4; i++)
nums.add(i, dice.random(6)+1);
You're mixing arrays and lists.
Have a look at the tutorial:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
http://docs.oracle.com/javase/tutorial/collections/index.html
Can you create a line of code, within a while-loop, that will create a new array AND change the array's name with each iteration of the while loop?
Example:
int size = 10;
int name_count = 1;
while(size <= 100)
{
//name_count is changing the name of the array by calling it
// "array1", "array2", etc...
//I know this may not be correct code for changing the name of
// the array, but it is suppose to get the point across.
int[] array(name_count) = new int[size];
for (int i = 0; i <= size; i++)
{ /* Adding numbers to an array */ }
size = size + 5;
name_count++;
}
Identifier names need to be defined at compile time. So you can't explicitly use a different variable name on each iteration of the loop.
Another problem with your pseudo-code is that, if the array were to be declared inside the loop, it would fall out of scope when the loop completes, so there wouldn't be much point.
To do something like this you need to use some collection to hold the arrays, and it would be easier to make them explicit objects instead of just arrays. Something like:
List<List<Integer>> listOfArrays = new ArrayList<List<Integer>>();
while (size <= 100) {
List<Integer> listOfNumbers = new ArrayList<Integer>(size);
/* insert loop here to add numbers to listOfNumber */
size += 5;
name_count += 1;
}
Then you can access each list of numbers using an index into listOfArrays -- equivalent to naming each one with the index, but handled at runtime instead of compile time.
You cannot change the array's name, It will just re-declare the array with each successful loop. (It will be a new blank array.) I think what you are looking for is a two dimensional array.
int[][] myArray = new int[3][3];