Store 2D Array Index in ArrayList? - java

I'm coding a Battleship game and I need some way to track where the ships have been placed. I'm thinking the best way of doing this is with an ArrayList. If I store the indices that are contained in a placed ship, then I can iterate through the ArrayList to signify it's an invalid position. For example, if I have a loop like so:
for (int j = 1; j < SIZE; j++)
{
for (int k = 1; k < SIZE; k++)
{
if ((cell[j][k].contains(click)))
{
cell[j][k].setColor(Color.blue);
}
}
}
I'd like to store the cell [ j ] [ k ] position in an ArrayList, and when it's time for the user to place the ship, a for loop is run to determine whether or not that cell is occupied. The problem is when I try to add to the ArrayList, I'm adding the actual cell, not the index. I want the actual position (x, y) to be stored in the List, but right now I'm storing the actual element.

Storing a list of x and y values is an ideal situation to use Java's point class.
ArrayList<Point> shipPositions = new ArrayList<Point>();
shipPositions.add(new Point(0, 0));
The ArrayList of points can be easily modified and iterated through to add and remove ship positions.

You can make a separate object for each ship. You could make a rather simple class with an x and a y float (or a Point to keep it simple) and then just make an array of the ships like so
Ship[] ships = new Ship[n];
or
ArrayList<Ship> ships = new ArrayList<Ship>();
and then you could get the value at ships[n] (for the 1st example) or ships.get(n) (for the 2nd example).
This would allow you to use this array for more than just positions and minimize excess and unnecessary code. :)

Related

Accessing (X, Y) coordinates in a one-dimensional double array with one element being X and the next being Y?

I have a one-dimensional double array that stores X and Y coordinates.
Element 0 would be the first X and element 1 would be the corresponding Y.
Element 2 would be the second X and so on.
Currently this is my code, but I was wondering if there is another way as this way is giving me some problems. The coordinates double array is already filled.
for(int i = 0; i < coordinates.length; i+=2)
{
double x = coordinates[i];
double y = coordinates[i + 1]
}
My professor stated that he requires us to use a one-dimensional array for this assignment. If there is no other way, I can probably work around my problem and just go with the above approach, but I was just wondering if there is another way of doing this.
Using these coordinates I have to draw a polyline.
Here is my code used to draw the polyline.
Polyline shape = new Polyline();
for(double coord : coordinates)
{
shape.getPoints().addAll(coord);
}
shape.setStrokeWidth(3);
return shape;
Here is an image of what is going on along with all the given coords.
http://i.imgur.com/sjJWmPJ.png
That extra line is bothering me.
-Edit: Thank you for everyone helping me. The problem was that my double array had a size of 500, and I was not using all of it, so most of the values were 0. I kept a track of how many coordinates I had and based my for loop condition on that rather than the length of the coordinate array.
Not exactly sure how to mark this as solved.
public static void main(String [] args){
int[] coordinates = new int[10];
int[] xArray = new int[10];
int[] yArray = new int[10];
for(int j = 0; j < coordinates.length; j++){
coordinates[j] = (int)(Math.random()*100);
System.out.println(coordinates[j]);
}
System.out.println();
for(int i = 0; i < coordinates.length; i+=2)
{
xArray[i] = coordinates[i];
yArray[i] = coordinates[i + 1];
System.out.println("x" + Integer.toString(i) + ": " + xArray[i]);
System.out.println("y" + Integer.toString(i) + ": " + yArray[i]);
}
}
I'm new so I dont know if i'll be any help, but the question was if there was any other way you could do it. This makes it so each coordinate is given a specific place in memory unlike in your for loop where it overrides x and y. I dont know how yours is filled so i just filled mine with random numbers.
It looks like the extra line there is coming from point (0, 0). I'm not very familiar with Java drawing tools, but it seems likely that (0, 0) is where the "pencil"'s position is initialized.
I've used Java drawing tools just a couple of times before, but I seem to remember there was some method you used to "lift the pencil" - otherwise, you would draw lines everywhere. Could that be what's causing the extra line? You would have to life the pencil, go to the first point, put down the pencil, and start drawing to fix the problem.
http://www.java2s.com/Tutorials/Java/JavaFX/0080__JavaFX_Polygon_Polyline.htm
it's amazing that method only need double array
so you don't need to use loop
Polyline shape = new Polyline();
shape.getPoints().addAll(coordinates);
shape.setStrokeWidth(3);
return shape;
also try to print your getPoints() value, it is any .clear method? maybe when you initialized the object, point(0,0) automatically added ad first

How to add / remove different class instances from arrayList stored inside a mulitidimentional array in java

My overall thought process may be off here so if there is a more logical solution to this feel free to suggest. The problem is this, I have a 2 dimensional array that I am treating as an x,y grid system. I would like to be able to store multiple class instances inside a single array index. my thought was to instead store an array list inside each array index as a sort of container for the objects. The problem is that I'm not sure how to address the list that is inside a given index at array[i][j].
One solution I considered is to create a templist and set tempList = array[i][j] edit tempList set array[i][j] = tempList. Sort of a switcheroo. Is there a better way to do this?
You can edit the lists directly, without any need for temporary variables.
To set a list:
array[0][0] = new ArrayList<>();
So you can fill the entire array with something along these lines:
int width = 100;
int height = 100;
List[][] array = new List[width][height];
for(int x = 0; x < width; x++){
for(int y = 0; y < height; y++){
array[x][y] = new ArrayList<Object>();
}
}
The array will have all it's elements set to null by default, so you will have to create a list at every index.
The above code will create an ArrayList at every position in the array, which you can then use just like any other list:
array[0][0].add(element); //Adds the element to the list at [0,0]
Object obj = array[0][0].get(0); //Gets the element we just added

I am confused on copying 2D arrays

I was reading this post on Stack overflow: copy a 2d array in java and I am a little confused on how the clone method works here...
public int[][] CopyMap(int[][] Map)
{
int [][] copy = new int[Map.length][];
for(int i = 0; i < Map.length; i++)
copy[i] = Map[i].clone();
return copy;
}
I know how to copy using enhanced for loops but I would like to fully understand this way.
1) Why do we put the Map.length in the first set of square brackets but not Map[0].length in the second set of square brackets for int[][] copy = new int[Map.length][];? Don't we have to initialize the length of the columns as well? I'm guessing that we can't clone a 2D array but we can clone a row or column at a time.
2) By cloning the columns one column at a time and putting it into our 2D array it sets the length of the columns for us?
3) Could we reverse this code by doing this
public int[][] CopyMap(int[][] Map)
{
int [][] copy = new int[][Map[0].length];
for(int i = 0; i < Map[0].length; i++)
copy[i] = Map[i].clone();
return copy;
}
4) Also copy[i] ? This is a 2D array, so shouldn't it be copy[i][] ? Or something like that.
In Java a 2D array is essentially an array of arrays (possibly with different lengths). It is important to remember this. For example, this is OK:
int[][] ar = new int[2][];
ar[0] = new int[8]; // ar[0][0..7]
ar[1] = new int[4]; // ar[1][0..3]
The syntax new int[8][10] can be used as a convenience to create 8 separate arrays of 10 elements each.
If you are familiar with C: an int[][] in Java is more similar to an int** in C.
Note: Map is a terrible name for a variable in Java; variable names generally start with lowercase letters and there is also a very common base container interface of the same name.
1) Why do we put the Map.length in the first set of square brackets but not Map[0].length in the second set of square brackets for int [][] copy = new int[Map.length][]; ?
Because we are starting with an array of Map.length int[]'s, and then cloning those int[]s one at a time.
Don't we have to initialize the length of the columns as well?
No, because when we go through each int[] in Map, we just use clone() to copy it: copy[i] = Map[i].clone().
By cloning the columns one column at a time and putting it into our 2D array it sets the length of the columns for us?
A "column" is just a concept you made up that is only relevant to tabular data (column-major tabular data in your specific context). Anyways, "setting the length" isn't exactly accurate because it implied that something whose length is being set existed in the first place; but when you do int x[][] = new x[5][], x[0] is null until you assign it to something. By cloning the int[]s one at a time, we're just... cloning them one at a time. So, yes, each clone will be the same size as the original.
3) Could we reverse this code by doing this
public int[][] CopyMap(int[][] Map)
{
int [][] copy = new int[][Map[0].length];
for(int i = 0; i < Map[0].length; i++)
copy[i] = Map[i].clone();
return copy;
}
No; and hopefully the reason why is clear now that you know that an int[][] is an array of arrays. The expression new int[][size] doesn't make much sense; it says that we want each int[] in the array to have a given size, but it doesn't say how many int[]s are in the array. It's wrong for the same reason that int[] x = new int[] is wrong.
4) Also copy[i] ? This is a 2D array, so shouldn't it be copy[i][] ? Or something like that.
No, it should be copy[i]. I'll leave figuring out the reasons as an exercise.

Fast hashing of 2-dimensional array

I'm building a Reversi player using the standard alpha beta pruning search algorithm. I'm trying to add a translation table to store previously calculated nodes in the search tree. So I need to hash a 2 dimensional array representing the game board (the state) and store a value for that.
I can't come up with anything better than a double for loop iterating over my arrays and adding all values together multiplying them with the offsets to get unique hash values.
#Override
public int hashCode() {
if (dirtyHash) {
int hash = 0;
for (int i = 0; i < Board.SIZEX; i++)
for (int j = 0; j < Board.SIZEY; j++)
hash += board[i][j] * (i + Board.SIZEY * j);
hashValue = hash;
dirtyHash = false;
}
return hashValue;
}
I suspect there must be a much smarter way to do this? Anyone got any ideas?
I would use java standard library as a first try:
int hash = java.util.Arrays.deepHashCode( board );
Once everything works well, profile your whole app, to check if the hashcode computation is really a performance bottleneck.
If you want to handle this yourself here is one way you could do it.
There are three values for each cell on the board: empty, black, white. That means you can use two bits per cell on the board. And since the board is 8x8 or 64 cells, you can encode the board in two long primitives. Maybe one of them tells you whether a particular cell is empty, and if it's not, the other tells you its color.
You do not even need to convert this representation into a 2D array. You can use bitwise operators on the longs directly in your methods to work with the board.
The hash value could then be the XOR of the two longs, or something like that.
You should be using a Zobrist hash for this. It is perfect for board games. It can also be updated incrementally as the board changes, instead of being recalculated from scratch every time. This makes it very efficient.
http://en.wikipedia.org/wiki/Zobrist_hashing
I'd suggest to following:
public int hashCode() {
int hash = 0;
for (int i = 0; i < Board.SIZEX; i++)
for (int j = 0; j < Board.SIZEY; j++)
hash = (hash) ^ ( (Math.pow(p,i)+Math.pow(p,j))* board[i][j]
return hashValue;
}
for p and q large 32-primes.
Why is that fast?
Calculatoin for a board is quite easy: the new can be calculated from the old with hash = (hash) ^ ( (Math.pow(p,i)+Math.pow(p,j))* board[i][j], iterating not over the whole board, but only the Changed stones. (if you add a black once with the hash for the black stone, if you change from black to white once with the black stone to remove it from the hash und once again with the white to add it)

Java: Searching in an array of objects, for 2 specific object values

I'm doing a project in Java which includes (x,y) coordinates.
I have created a class of Cell which has protected integers X & Y;
Upon initialization, i do a for loop which sets an array of cell by multiplying the X & Y given by the user, say if X= 10 and Y = 10, i create an array of cells[100].
However, how can i search the array fast, without doing a for loop and checking each individual value very time?
Say I'm looking for the object that contains X=5 & y = 3.
I know i can go through with a for loop looking for object with values x and y, but i was wondering if there is a way to do a binary search and find "a bit faster" the object[i] that contains X=5 and Y=5.
Thank you very much.
The way to do this is to arrange the Cell objects in the array in a way so that there is a simple mapping from an X,Y coordinate to the Cell's index in the array.
For example, lets assume that X and Y go from 1 to 10. Suppose that we then arrange the Cells so that:
array[0] = Cell(1, 1);
array[1] = Cell(1, 2);
...
array[9] = Cell(1, 10);
array[10] = Cell(2, 1);
array[11] = Cell(2, 2);
...
array[99] = Cell(10, 10);
It should be easy to see that we can calculate the index of Cell(i,j) in the array and fetch the cell as follows:
public Cell getCell(Cell[] array, int i, int j) {
int index = (10 * (i - 1)) + (j - 1);
return array[index];
}
This is the approach that programming languages that support N-dimensional array types typically use to implement them.
This can be trivially modified to deal with cases where:
the constant 10 is something else
the matrix is not square,
the matrix has more than two dimensions
indexes run from 0 to N - 1 instead of 1 to N
etcetera
There are various other ways that you could represent 2-D matrices in Java. The simplest one is just using a Cell[][] cells which allows you to access cells as (for example) cells[i-1][j-1]. More complicated representations can be designed that use less space if the matrix is sparse (i.e. cells are missing) at the cost of more complex code and slower access times.
It sounds like (if you want to use binary search, anyway) you're setting element 0 to the Cell with x = 0, y = 0; element 1 to x = 0, y = 1, etc. If so you should be able to trivially compute the exact index of a given Cell:
// contains the Cell with x = desiredX, y = desiredY
yourArray[desiredX * X + desiredY];
If this is what you're doing, however, it'd probably be simpler to just make a 2-dimensional array:
yourArray = new Cell[X][Y];
...
yourArray[desiredX][desiredY];
the above two answers show the trivial method for getting the array index fast. id like to propose an alternative- use hashmaps with key, value pairings. the value could be objects. accessing hashmap elements run in constant time..

Categories