so I am new to programming and having some issues with classes. I am using the lens next brick. There is a class from the libuary called Node. It takes a X and Y. Like so:
Node nodeNameOne = new Node(2,3);
What I want to do:
I have a 12 by 12 array. And for each position in the array I want to get its X and Y and create a new node. The problem is I want to automatically change the " nodeNameOne" .
My solution was to create a intiger variable and increment it, then do a .to string and use that as the nodes name by when I use my intiger variable name it uses the name of the variable not the value within the variable.
I have looked at other posts that sujest using "Class.newInstance" but I can't get this to work.
Any help is appreciated.
Thanks
UPDATE:
I have a 12 by 12 array. I will scan the array and when I detect a 0 in any position of the array i want to create a new Node with the X and Y of the array position.
because it is a 12 by 12 array there are 144 possible places that 0 can occur.
therefore the code that is needed to make a new is node is:
Node nodename = new Node(x,y);
I want to automate the instance name: "nodeName" to use a string variable, that I will get from:
int nameOfNode= 0;
String temp = Integer.toString(nameOfNode);
Node temp = new Node(x,y);
nameOfNode++;
the error i get is that it says that temp is already used, but i know that. i want it to use the value of temp not the name "temp". - i hope this is clearer.
What you want is probably an array. A twodimensional array is a mapping from (i,j) --> Node[i][j]:
// Step 1 and 2: Create and add nodes
Node nodes[12][12];
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++) {
nodes[i][j] = new Node(i, j);
mesh.add(nodes[i][j], 0);
}
}
You can then refer to a node by using numbers (or integer variables):
// Step 3: Connect nodes:
mesh.connect(nodes[2][3], nodes[2][4]);
mesh.connect(nodes[2][3], nodes[3][3]);
mesh.connect(nodes[2][4], nodes[2][5]);
...
I think you want a java.util.Map;
A Maps is an object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value. You can use Strings "x,y" as keys for your nodes objects then you can retrieve your node objects by strings the way you want.
you can use an map like this:
final Map<String,Node> nodesMapedByName = new HashMap<>();
(...)
//asssuming x and y are integers, this will create an
//new node for x and y and put it in the map using the string
//"x,y" as key
nodesMapedByName.put(x + "," + y, new Node(x,y);
(...)
//asssuming x and y are integers, this will retrieve the node
//mapped by the String "x,y"
final Node someNome = nodesMapedByName.get(x + "," + y);
Related
This question is regarding libGDX, but I think it's in fact more Java/algorithm related.
Part of my game includes placing 20 elements out of predefined 30 elements list on a screen (so effectively a coordinate system) in 20 partially-predefined places.
By partially predefined I mean that they are predefined for each screen, but there can be dozens of screens, so they can be as well treated as random.
The elements will be selected randomly, but the elements close to each other must be unique. By close I mean in range of some arbitrary defined distance X. Effectively each place will have around 3 'close neightbours'.
The best way I can think of so far is as follows:
Calculate the distance between all places. If a given distance between A and B is lower than X put two entries in a map - one (A,B) and one (B,A)
Now start filling the places with elements
For each place create a list with all neightbours using the map from point 1 (let's call it N-list)
For each place create a temporary list with all possible (30) elements (let's call it E-list)
Get a random element from E-list
Iterate through N-list. For each place from the list get an element currently there (if there's any). For this a (place, element) map is needed, so it will be filled as the algorithm progresses.
If the found element is equal to the current random element remove this element from E-list and this place from N-list and come back to point 5
Proceed until all places are filled
Step 1 is in fact a separate algorithm, that probably can be tweaked, ex. if we calculated the A->B distance we don't need to calculate B->A, but that needs an additional map to store calculation info, etc.
I would like to know what you think of this way and if you have any ideas for a better one.
Thanks in advance for your answers.
P.S. Perhaps the terms I used could be better chosen, but I'm not a native speaker and I don't know English math terms :-)
Ok, I think I understood your solution and this is what I thought of initially. But I think it can be slightly optimized by eliminating extra pairs and maps (or maybe not :)
First, create a map of locations where key is location position (or the location itself) and value is a list of location's parents who fall within the close range. Yes it will have multiple parents, not children, it is actually the same but parents are more fitting here as we'll see.
ArrayList<Place> place_list; // your list of places here
ArrayList<Element> element_list; // your list of elements here
HashMap<Place,ArrayList<Place>> parent_map = new HashMap<Place,ArrayList<Place>>;
ArrayList<Place> a;
for (int i = 0; i < place_list.size() - 1; i++) {
Place place1 = place_list.get(i);
for (int j = i + 1; j < place_list.size(); j++) {
Place place2 = place_list.get(j);
int dist = getDistance(place1, place2);
if (dist > DISTANCE_THRESHOLD) continue;
// if this place is within range,
// add parent place to its list and put/update it to the map
a = parent_map.get(place2);
if (a == null) a = new ArrayList<Place>();
a.add(place1);
parent_map.put(place2, a);
}
}
Now we have a map of all places that have parents. Next we do the following: if place does not have parents, it can choose any random element freely. If it does have parents, it checks what elements parents own and reduces the available set of elements. After the set was reduced, any random element can be chosen from it.
HashMap<Place,Element> used_place_map = new HashMap<Place,Element>(); // key is place, value is assigned element
ArrayList<Element> tmp_element_list;
for (i = 0; i < place_list.size(); i++) {
Place place = place_list.get(i);
a = parent_map.get(place);
if (a == null) { // this place has no parents, use elements freely
tmp_element_list = element_list;
} else { // if it has parents, they have already registered their elements in used_place_map
tmp_element_list = new ArrayList<Element>();
// create list of available elements, lame
for (j = 0; j < element_list.size(); j++) tmp_element_list.add(element_list.get(j));
// now reduce it, very lame, sorry
for (Place pl : a) {
Element used_element = used_place_map.get(pl);
for (j = 0; j < tmp_element_list.size(); j++) {
if (used_element.equals(tmp_element_list.get(j)) {
tmp_element_list.remove(j);
break;
}
}
}
}
// finally, get the random index on (probably reduced) array
int element_id = Random.nextInt(tmp_element_list.size());
Element element = element_list.get(element_id);
// store our choice as future parent
used_place_map.put(place, element);
}
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've been studying for my upcoming Java exam, and i'm having a hard time wrapping my head around 2D arrays. I have the basics down, such as creating and initializing a 2D array, but when it comes to inserting, deleting, or even sorting through one, I get pretty confused. My professor spent all of 10 minutes going over the basics but on our exam, we are expected to know how to create a 2D array of objects and manipulate the data by inserting, deleting, and sorting the objects in the array. He makes us hand-write all of our code on our exams, so no computers are allowed to assist in the process. I've spent hours pouring over examples both here and on other sites, but I still don't feel like I understand the material well enough to hand write all my code and get it right.
My confusion mostly stems from the nested for loops usually used to move thru a 2D array. I can see how other people do it and copy that, but I still don't understand why the loops work as they do. I'm sure i'm in the minority here, but for whatever reason the logic behind it has me completely lost.
Take this(albeit poor) example i've been working on to help myself understand 2D arrays(as well as the rest of the exam material). Say you run a car dealership and you want to order cars to fill your stock. The program starts with a top abstract class that describes the cars you are selling in general(in my case Audi). The dealership offers 4 models of Audi's, an A4, A6, A8, and R8. All these cars(classes) inherit methods from the super, named Audi. I then want to create a 2D array to store the cars in stock. This will be used in another class defined by me, including methods to search(), delete(), and sort(). Let's call it AudiDealership. The dealer can only hold 3 of each model, so the array would be something like Audi[4][3]. The A4's would fill the first row, subscript 0, A6 fills subscript 1, ect. How would I set up the for loops to insert/delete from the proper row? I obviously don't want an A4 inserted into a row that should hold an A6, and so on.
Again, I can stare at code all day and copy it, but I want to understand why/how the loops work as they do. I apologize if this topic seems trivial or has been beaten to death, but all the reading i've done before posting this has left me just as confused as before. Many of you on this site are fantastic teachers in your own right, so I thought someone may be able to explain this in a way that I can understand. My professor hasn't been any help in this regard, so i'm using external means to try and figure things out. I greatly appreciate any advice or explanation in advance :)
It helps to think of 2D arrays as arrays that hold other arrays. Such as Cars[0][5] is accessing a car array at 0 and the actual car is found in position 5 of that array. Cars[1][5] would access the second car array at position 1 and the car is found at 5 of the array that's in position 1. This code might help you understand it a bit more:
public class TwoDArray {
public static void main(String[] args)
{
Cars[][] cars; // declaring my 2D array.
cars = new Cars[4][]; // making the x axis 4 cars wide.
// now we will step along the x axis and create a Cars array in each slot.
for ( int a = 0; a < cars.length; a++) // cars.length = how wide.
{
cars[a] = new Cars[3]; // creating a new Cars[] in each slot of our 2D Car array # position a.
//cars[a] = new 1D Cars array in slot a, length of 3.
}
// Note that we could have also created our array like this.
// Cars[][] cars = new Cars[4][3];
for ( int x = 0; x < cars.length; x++) //stepping along the x axis. cars.length = how wide.
{ //every time we step thru x we will execute this next loop.
for ( int y = 0; y < cars[x].length; y++) // stepping along the y axis. cars[x].length = how long.
{ // this loop will cycle through the y axis each time we increment x
cars[x][y] = new Cars( 2014, "someAudi", x + " " + y ); // creating a new car(s) # x,y position.
}
}
// now to just print them.
for ( int x = 0; x < cars.length; x++) //stepping along the x axis again.
{
for ( int y = 0; y < cars[x].length; y++) // stepping along the y axis.
{
System.out.println(cars[x][y].getYear() +
" " + cars[x][y].getModel() +
" " + cars[x][y].getName() +
" " + cars[x][y].getManufacturer()); // the super method.
}
}
//INSERTION.
// To insert into your array, you simply need to provide the coordinates to insert the new Car(s) object.
// This next line will insert a new Car into the array at position 1 and the number 2 element of that array.
cars[1][2] = new Cars( 2014, "someAudi", "My Favorite Car!");
System.out.println(); // Just adding a space between outputs.
for ( Cars[] c: cars) //extracting each Cars array and name it c from the 2D Cars array named cars.
{ //basically stepping along the x axis and getting each array stored in x.
for ( Cars car: c) // Now we are stepping along the y axis.
{ // We are getting each individual Cars object and naming it car
// from each Cars[] named c from our first loop.
System.out.println(car.getYear() +
" " + car.getModel() +
" " + car.getName() +
" " + car.getManufacturer()); // the super method.
}
}
// NOTE* if you wish to insert a new element and do not have extra capacity then you will need to
// create a larger array # cars[x]. cars[x] = new Cars[newSize];.
// DELETION.
// To delete an element you can just simply overwrite it.
// such as:
cars[1][1] = new Cars( 2014, "someAudi", "new Audi"); // Essentially we deleted and inserted a new object
// at position [1][1].
// If you just want to completely remove the element then you will need to update the size of the array.
// You can define a new array to hold the values of the old array minus the element that should be deleted.
Cars[] newArray = new Cars[cars[2].length - 1]; // We will use the array stored in cars[2] for this example.
// we set the length to one less to completely get rid of the
// old element.
int deleteThisPosition = 1; // We will use this variable to store the position that will be deleted from
// the array stored in cars[2].
int newArrayPosition = 0; // We will use this to increment our position in the new array along with `a`
// in the next for loop.
for ( int a = 0; a < cars[2].length; a++)
{
if ( a == deleteThisPosition) // if it reaches this position we will advance `a` and exclude it from
a++; // our new array.
newArray[newArrayPosition] = cars[2][a]; // we will store the value # position `a` from the array in cars[2]
// into our newArray # position `newArrayPosition`.
newArrayPosition++; // incrementing our variable to stay parallel with the array in cars[2].
}
//Now we can just assign the newArray to cars[2]. You will notice that Car `2 1` is no longer present.
cars[2] = newArray;
System.out.println(); // Just adding a space between outputs.
for ( Cars[] c: cars)
{
for ( Cars car: c)
{
System.out.println(car.getYear() +
" " + car.getModel() +
" " + car.getName() +
" " + car.getManufacturer()); // the super method.
}
}
}
}
Here are the other classes from your example.
Audi class:
public abstract class Audi {
public String getManufacturer() { return "Audi"; } // method from this super class.
}
Cars class:
public class Cars extends Audi{ //extending Audi.
private String model;
private String name;
private int year;
Cars(int year, String model, String name)
{
this.year = year;
this.model = model;
this.name = name;
}
public String getName() { return name; }
public String getModel() { return model; }
public int getYear() { return year; }
}
If you run the code you will notice the pattern in the names of the cars.
Output:
Notice the pattern in each car's name, the unique column. It corresponds to how we stepped through our loops. We started with x and for each x we looped through y. x + " " + y was how we named each car in the code above.
Audi[4][3] cars = ... // your 2D array of all cars
As you correctly specified,
The A4's would fill the first row, subscript 0, A6 fills subscript 1, ect.
which translates to cars[0] holds Audi[] with A4 instances, cars[1] holds Audi[] with A6 instances etc.
OK, so
Audi[] A4s = cars[0];
Audi[] A6s = cars[1];
...
Then you could say that
Audi A4_1 = A4s[0];
Audi A4_2 = A4s[1];
Audi A4_3 = A4s[2];
...
And repeat it for each car you have. But this is a wrong approach. First we generalize access to each car.
If you want to traverse specific cars in each model array, you need to have a for-loop with index called, say, specificCarIndex. Loop to traverse an array of A4s will be simple:
for (int specificCarIndex = 0; specificCarIndex < 3; specificCarIndex++) {
// Here A4s[specificCarIndex] contains an object of concrete Audi car of model A4
}
To traverse array of another model (like A6) you do the same, replacing A4s with A6s and so on.
Now we need to generalize everything.
for (int carModelIndex = 0; carModelIndex < 4; carModelIndex++) {
// Here cars[carModelIndex] holds an array of specific Audi model as you mentioned before
}
cars[carModelIndex] essentially is Audi[] A4s if carModelIndex == 0, then Audi[] A6s if carModelIndex == 1 and so on.
Now that we know how to access array of each Audi model, and we know how to access individual cars in each model array, we combine the two:
for (int carModelIndex = 0; carModelIndex < 4; carModelIndex++) {
for (int specificCarIndex = 0; specificCarIndex < 3; specificCarIndex++) {
// Here cars[carModelIndex][specificCarIndex] holds an object of type Audi which refers to a specific car
// If double index seems difficult, consider this:
// Audi[] audis = cars[carModelIndex] (array like A4s, A6s...)
// Audi audi = audis[specificCarIndex] (specific car)
// Just as in the examples before for-loops.
}
}
Let me give you an example:
StringBuilder output = new StringBuilder();
for (int i = 0; i < table.length; i++) {
for (int j = 0; j < table[i].length; j++) {
output.append(table[i][j]);
}
output.append("\n");
}
This would be the code to loop through a 2 dimensional array.
The code goes directly into the first row. This is the i-value.
As you want to loop through every column of the row,
you need to know the length of the row to loop through it.
So you start in the first row, and go right to the end which is table[i].length.
In the first row the first length would be table[0].length.
And this length is 3 as you have 3 columns in each row.
As we're now done with looping through the first row, we get to second row.
By going into the second row i increases by one.
So our pointer shows now in row 2 (The i in table[i].length is now 1 because it always starts at 0) and so on.
Our pointer goes through every row and thats just how it works.
with every new row the pointer of i increases by 1 (that's the i++ in the for loop).
With every new column in one row the j increases and the i stays the same.
The i only changes when you're entering a new row.
And the j changes by entering a new column.
Hope this helps ;)
EDIT.:
Another example :
if you would like to get the value of the 3rd column in the 4th row:
The value you want is inside here: table[3][2];
Remember arrays always start counting at 0. :)
I have 2 arraylists. I am using one arraylist as a key to store values.
In nutshell, my code is as below.
for(int i=0;i<transactionid.size(); i++)
{
if(transactionid.get(i).equals(transactionnumber))
{
transactionvalue.set(i, transactionvalues);
}
}
In the above program snippet, transactionid is used to store my key values. If there is a match in the key value, I am updating the arraylist transactionvalue.
So far so good. But now, I want to update another arraylist diskitemvalues based on the above two arraylist values. The update is something like below.
for(int i=0;i<transactionid.size(); i++)
{
if(transactionid.get(i).equals(transactionnumber))
{
try
{
/* Open file to read contents*/
while ((strLine = br.readLine()) != null)
{
/* Get the values of transactionvalue arraylist and update them. */
/* The transactionvalue arraylist contains values like {X Y} */
/* So my update in the diskitemvalues arraylist
should be X = so & so Y = so & so based on file */
I have to navigate to the particular value in the transactionid arraylist and for that particular key, I have to find out the corresponding values in the transactionvalue arraylist and update the diskitemvalues arraylist for all values present in the transactionvalue arraylist.
Example:
Transactionid transactionvalue
1 X Y
2 M N
For transactionid = 2, my diskitemvalues [2] should have M = so & so and N = so & so from the input file. If it is transactionid = 1, my diskitemvalues[1] should have X = so & so and Y = so & so from the input file.
I'm trying to add newly created objects to a grid and to a graph. Specifically, how to efficiently add nodes to a graph with a for loop. They grid has been set up as a double array, in order to update the initial view. (The object grid is the model and updates the view via push). I also set up a HashMap using the items in i and j within the for loops in order to define the object's keys. However, in order to set up a graph in order to later calculate the shortest path from node to node, I need to add these nodes to a Graph. I would like to use Djikstra's algorithm to calculate the shortest path. I could create a conditional statement to define what are corner nodes and edge nodes in the grid and define what items would have bi directional edges but this seems to be a 'long cut'. Is there any way to add nodes to a graph with a pre determined matrix size, such as for example 20 X 20, similar to a double array?
Below is the constructor code on how I am creating the first two items (creating double array and HashMap):
// **Constructor
// Construct a new Grid object. Sets up a HashMap of square object in order efficiently to get
// and add Square objects later.
public ObjectGrid(Integer width, Integer height)
{
// View
gui = new GUI(); // Instantiate GUI
boardView = new BoardView(width,height); // Instantiate BoardView
// Initialize Gui, set time and add simulation event listener to model (ObjectGrid)
gui.initGUI(BoardView);
gui.addSimulationEventListener(this);
// Initialize turnInSteps variable count to 0
turnInSteps = 0;
// Initialize numberOfDays variable count to 0
numberOfDays = 1;
// Instantiate HashMap
objectHashMap = new HashMap();
// Declare new object grid using double array of type objects.
// Size determined by parameter Integer values in constructor
myObjectGrid = new ObjectType[width][height];
// Instantiate Graph object
Graph graph = new ListGraph();
// For loop sets up the initial grid with ObejctType using a double array. After
// the completion of this loop, the grid will have XXX objects in the grid
// each with a reference to an object. Objects are also added
// to HashMap using coordinates as keys and square objects as values.
for(int i = 0; i < width; i++)
{
// Iterate through rows
for(int j = 0; j < height; j++)
{
// Iterate through columns
myObjectGrid[i][j] = new ObjectType(); // Instantiate a new Square at each row/column using default constructor
gridView.addObjectView(myObjectGrid[i][j].getObjectView(), i, j); // Add object view to each row/column placement
String hashMapKey = (i + ", " + j); // Use values from i and j as Key for objects HashMap
myObjectGrid[i][j].setID(hashMapKey); // Add ID's for each ObjectView to display in object using values from i and j
objectHashMap.add(hashMapKey, myObjectGrid[i][j]); // Add object to HashMap using string value of coordinates as key
listGraph.add(myObjectGrid[i][j]);
// Pseudo code
if (i != (width-height) && (j != height) etc)
{
listGraph.addBidirectionalEdge(mySquareGrid[i][j], (mySquareGrid[i][j+1]), 1);
listGraph.addBidirectionalEdge(mySquareGrid[i][j], (mySquareGrid[i+1][j]), 1);
listGraph.addBidirectionalEdge(mySquareGrid[i][j], (mySquareGrid[i+1][j+1]), 1);
}
}
}
}
With the unit tests that I did the vertices in the graph return null.
The reason is the following lines:
listGraph.addBidirectionalEdge(mySquareGrid[i][j], (mySquareGrid[i][j+1]), 1);
listGraph.addBidirectionalEdge(mySquareGrid[i][j], (mySquareGrid[i+1][j]), 1);
listGraph.addBidirectionalEdge(mySquareGrid[i][j], (mySquareGrid[i+1][j+1]), 1);
You are in the middle of initialization of mySquareGrid and create edges with nodes from future. These nodes with j+1 and i+1 are nulls at this moment.
Try the simplest solution - after grid initialization do the same cycling through grid and create graph's edges.
Also, you can try to change it to the following:
listGraph.addBidirectionalEdge(mySquareGrid[i][j-1], (mySquareGrid[i][j]), 1);
listGraph.addBidirectionalEdge(mySquareGrid[i-1][j], (mySquareGrid[i][j]), 1);
listGraph.addBidirectionalEdge(mySquareGrid[i-1][j-1], (mySquareGrid[i][j]), 1);