comparing multi dimension arrays - java

I have 2 images and each is partial of a complete image, and the 2 combined could create the complete image.
However there is overlap on the 2 images, and I am trying to create a program that will find where the top row of image2 meets whichever row of pixels in image 1.
I created a for loop to gather each row of pixels per image in an array.
this is my code:
int row = 0;
for (int i = 0; i < imageArray1.length; i++) {
for (int j = 0; j < imageArray1[i].length; j++) {
if (imageArray1[i][j] == (imageArray2[0][0])) {
row = imageArray1[i][j];
}
}
}
the problem is I am pretty sure I am only gathering a with the individual pixel that is top left of the second image, rather than the whole row.
Any ideas how to get around this?
new to java

You need to cross check each rows in image1 against each rows in image2. Therefore, 3 levels of looping: 1) loop through the rows in image1 2) loop through the rows in image2 3) loop through the columns in the current row in image1 and image2 to decide if they are overlapping
int overlappingRowInImage1 = 0;
int overlappingRowInImage2 = 0;
int[][] imageArray1 = null;
int[][] imageArray2 = null;
// loop through the rows in the first image
for (int row1 = 0; row1 < imageArray1.length; row1++) {
boolean foundIdenticalRow = false;
// loop through the rows in the second image
for (int row2 = 0; row2 < imageArray2.length; row2++) {
foundIdenticalRow = true;
// two rows are identical if each column in both rows are the same
for (int col = 0; col < imageArray1[row1].length; col++) {
if (imageArray1[row1][col] != (imageArray2[row2][col])) {
foundIdenticalRow = false;
break;
}
}
if (foundIdenticalRow) {
overlappingRowInImage1 = row1;
overlappingRowInImage2 = row2;
break;
}
}
if (foundIdenticalRow) {
System.out.println("Row " + overlappingRowInImage1 + " in image 1 is overlapping with Row " +
overlappingRowInImage2 + " in image 2");
break;
}
}

You need to fix the imageArray2[0][0] so it's always comparing with the first index of imageArray2 only. You need to iterate your imageArray2 along with imageArray1 for full comparison. For this I would suggest you to use a nested for loop for imageArray2.

Related

Storing all diagonals from top right to bottom left in array

I am trying to store all of the values in the matrix from the top right to the bottom left and store them in an array.
int matrixSample [][] = {
{6,4,1,4},
{7,5,4,4},
{4,4,8,3},
{4,4,8,3}
};
The output should be
[4,1,4,4,4,3,6,5,8,3,7,4,8,4,4,4]
I can get the bottom right diagonal
static int[] getAllDiagonalsInMatrix(int matrix[][]){
// Sum of arithmetic progression
int diagonal[] = new int[matrix.length * (matrix.length + 1)*2];
int index = 0;
for(int row = 0; row < matrix.length; row++) {
for(int col = 0; col < matrix[row].length - row; col++) {
diagonal[index++] = matrix[row + col][col];
}
}
return diagonal;
}
Is this even possible to do using the same two loops by adjustments made in the loops above?
Okay, here is my thought process on your problem. However, I'm going to print values instead of collecting them to make it a little easier on me and keep the solution easy to read.
First, how do you get a diagonal? We need to do this frequently so lets start by making a function for that. Maybe we could pass in the top left corner of the diagonal and go from there.
public void getDiagonal(int[][] array, int row, int col) {
// While row and col are within the bounds of the array
while (row < array.length && col < array[row].length) {
// Print element in diagonal
System.out.println(array[row][col]);
// Diagonal moves from top-left to bottom-right
row++;
col++;
}
}
Now that we have a function to get a diagonal, we just need a way to call it. Essentially, we just need to follow an L shape going from the top-right to the top-left to the bottom-left.
// Get diagonals starting in the first row with a column > 0
for (int col = array.length - 1; col > 0; col--) {
getDiagonal(array, 0, col);
}
// Get all diagonals starting from the left most column
for (int row = 0; row < array.length; row++) {
getDiagonal(array, row, 0);
}
Now that we have a working way to iterate through the values, we can rewrite it to save the values into an array instead. You could also choose to remove the function entirely now that you have a process.
Edit: I almost forgot, but the mathematical solution you were looking for is as follows.
for (int row = 0; row < array.length; row++) {
for (int col = 0; col < array.length; col++) {
// Index along diagonal
int diagonal = Math.min(row, col);
// Which part of L contains value
if (col >= row) {
int start = array.length - 1 - (col - row);
int passed = start * (start + 1) / 2;
solution[passed + diagonal] = array[row][col];
} else {
int start = array.length - 1 - (row - col);
int passed = array.length * array.length - 1 - start * (start + 1) / 2; solution[passed - array.length + 1 + row] = array[row][col];
}
}
}
One solution is to iterate through a matrix where you consider positions outside of the matrix, but exclude every index out of bounds.
static int[] getDiagonals(int[][] mat) {
int diagonal[] = new int[mat.length * (mat[0].length)];
int index = 0;
int yStart = -mat[0].length;
for (int y = yStart; y < mat.length; y++) {
for (int x = 0; x < mat[0].length; x++) {
if (y + x >= 0 && y + x < mat.length) {
diagonal[index++] = mat[y+x][x];
}
}
}
return diagonal;
}
Might not be optimal as you are effectively traversing a matrix nearly twice the size, but it is pretty intuitive.

Check to see if two dimensional array Index is empty, if it is not generate a new Index

So I am basically creating a sort of ring toss application. I create a two dimensional array, "Game Board" as you will, populate the board with fifteen prizes in random locations each time the program is run. Then, I am to generate as if somone throws ten rings at the Index and mark where it lands and if it lands on a prize you get that prize if it doesn't you of course don't get any prizes.
Here I am having trouble generating all 15 prizes... I can print some prizes on the board but it never comes out quite at 15...
Here is the class that sets the prizes in random indexes "array" is my two dimensional array and prizes is an ArrayList that contains the prize list...
public static void setPrizes() {
for (int i = 0; i <= 15; i++) {
row = (int) (Math.random() * 5);
col = (int) (Math.random() * 5);
prizes.add("puzzle");
prizes.add("ball");
prizes.add("cash");
item = prizes.get(0 + (int) (Math.random() * 3));
if(array[row][col].equals(" ")){
array[row][col] = item;
}else{
inp = prizes.get(0 + (int) (Math.random() * 3));
array[row][col] = item;
}
}
}
I can not understand why the if statement wont realize that a prize has already been placed there.
I Generated my board like this...
public static String[][] genBoard() {
for (int row = 0; row < array.length; row++) {
for (int col = 0; col < array[0].length; col++) {
array[row][col] = " ";
}
}
return array;
}
The Board after the prizes have been generated...
public static void prizeBoard() {
System.out.println("The Board");
for (int row = 0; row < array.length; row++) {
for (int col = 0; col < array[0].length; col++) {
System.out.print("[" + array[row][col] + "]");
}
System.out.println();
}
}
You seem to have a few errors here:
Firstly you are using a double random and then rounding. Better is using a single Random object and the nextInt method.
Secondly, your for loop uses <= rather than < so it will be called 16 times rather than 15.
Thirdly, in each iteration you generate a location and then store an item there whether it already has one or not - both branches of your if statement assign item to the location. Whenever you generate an overlap you'll just overwrite the current item.
Fourthy, you are adding 3 new prizes in every iteration. Ideally that code would be in a constructor but, at the very least put it outside the loop.
Taking all these into account you would get:
Random rand = new Random();
List<String> prizes = Arrays.asList("puzzle", "ball", "cash");
int itemCount = 0;
while (itemCount < 15) {
row = rand.nextInt(5);
col = rand.nextInt(5);
if (!array[row][col].equals(" ")) {
array[row][col] = prizes.get(rand.nextInt(prizes.size()));
itemCount++;
}
}

BufferedImage to 2D Array: Finding pixelated edges

I'm trying to calculate the edges of a black object within a .png file. And by that I mean find the column and row values that makeup a box that encapsulates an object. I attached a link to the photo I created which draws the box according to the values I find. As you can see the top, bottom, and right lines seem to line up correctly, but if you zoom in to the left line, part of the image is outside of the box. Why is that? I have an algorithm which I'll post below that searches every pixel in the array and finds the last occurrence of pixel values != 0 for the top, bottom, left and right sides. For some reason that extra image on the left side is registering pixels that are == 0... Are the values being rounded down to zero? If somebody could explain what is happening that would be great.
Here is a link to the image: http://i.imgur.com/UG8Cghe.png. You really have to zoom into the left side to see what I am talking about. Downloading the image and viewing is probably a necessity. It is a VERY small detail.
Here is the method that converts the BufferedImage(.png) to a 2D Array:
private static int[][] loadImageTo2D(String file_path)
{
img = null;
try { img = ImageIO.read(new File(file_path)); }
catch (IOException e) { System.out.println(e); }
int width = img.getWidth();
int height = img.getHeight();
int[][] pix = new int[height][width];
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
pix[row][col] = img.getRGB(col, row);
}//for
}//for
return pix;
}//loadImageTo2D
Here is how I am searching for the sides:
private static int[] getPerim(int[][] pix)
{
//Array holds object boundary edges.
int[] lines = new int[4];
lines[BOTTOM] = 0;
lines[TOP] = pix.length;
lines[LEFT] = pix[0].length;
lines[RIGHT] = 0;
//Top down iteration, find the first and last row and column of the
//actual graphic.
for (int row = 0; row < pix.length; row++)
{
for(int col = 0; col < pix[0].length; col++)
{
if (pix[row][col] != 0)
{
if (row < lines[TOP]) { lines[TOP] = row; }
else if (row > lines[BOTTOM]) { lines[BOTTOM] = row; }
else if (col < lines[LEFT]) { lines[LEFT] = col; }
else if (col > lines[RIGHT]) { lines[RIGHT] = col; }
}//if
}//for
}//for
return lines;
}//getPerim
I'm then using lines[] to draw the blue box you see in image. Help!
Drop the else part of if else and make all of them ifs . Only one of those if elses can be executed. What happens if pixel is the most down and most left pixel? It will be only used as the most bottom one, as the if-else statement won't get to the col part. I suggest you change it to
if (row < lines[TOP]) { lines[TOP] = row; }
if (row > lines[BOTTOM]) { lines[BOTTOM] = row; }
if (col < lines[LEFT]) { lines[LEFT] = col; }
if (col > lines[RIGHT]) { lines[RIGHT] = col; }
And no, you can't group left border with right border, as they can be on the same pixel.

Can I simplify this for loop?

The following segment of code is from a system that generates a 5 by 5 grid of JButtons. I need to iterate over an ArrayList of JButtons and pass the row and column of the JButton into the ButtonListener's constructor. The way the code is currently shown below works, but I was wondering if I could clean up the code at all or re-factor in any way. I seem to have a lot of instructions for trying to construct a grid.
int row = 1, col = 1;
for (JButton curButton : view.getButtons()) {
curButton.addActionListener(new ButtonListener(row, col));
row++;
if (row > 5) {
row = 1;
col++;
}
}
Is there any way I can improve the quality or simplify the above code segment?
int iterator = 0;
for (JButton curButton : view.getButtons()) {
curButton.addActionListener(new ButtonListener(iterator%5 + 1, iterator/5 + 1));
iterator++;
}
Note here that I'm using integer division, which always rounds down. iterator/5 + 1 will map {0,1,2,3,4,5,6,...} to {1,1,1,1,1,2,2...}
Can't you have:
col = row = 5;
for (int i = 0; i < col; i++) {
for (int j = 0; j < row; j++) {
curButton.addActionListener(new ButtonListener(i, j));
}
}
Might have to make col and row 6 or make i and j start at a different number.

Randomize tictactoe

A while I did an assignment creating a tictactoe program through eclipse. It works well enough, with me clicking empty boxes to place O's, and the program inputting X's afterward. However, I was using a pretty simple code for the placement of X's:
public int putX(){
for(int i=0; i<3;i++)
for(int j = 0;j<3;j++) {
if(position[i][j]==' ') {
position[i][j]='X';
return 0;
}
}
return -1; //some error occurred. This is odd. No cells were free.
}
Because of this, the X's are just placed in the row of each column, going down until the next column. Can someone show me a simple way to randomize this program?
What we want to do is generate an array of all the possible points, and pick one of those points at random. We use a for loop to iterate through all points in the 3x3 array, and add the valid ones to our temporary array, and then we choose a random index, and place an X there.
String[] list = new String[9]; // maximum 9 points
int size = 0;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if(position[i][j] == ' ') {
list[size] = "" + i + j;
size++;
}
}
}
int index = (int) (Math.random() * (size+1));
position[Integer.parseInt(list[index].charAt(0))][Integer.parseInt(list[index].charAt(1))] = 'X';
Alternatively, instead of storing the x,y coordinates of the point in a String we could store them in a java.awt.Point like so:
Point[] list = new Point[9]; // maximum 9 points
int size = 0;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if(position[i][j] == ' ') {
list[size] = new Point(i, j);
size++;
}
}
}
int index = (int) (Math.random() * (size+1));
position[list[index].getX()][list[index].getY()] = 'X';
As you can see, the code for using a Point is practically the same, but instead of parsing the coordinates out of the String, we can just access them directly from the Class.
You should also check to make sure that there are some elements left, by checking if size is still 0 after the for loop. If so, you should probably return -1 (what your existing code does). Otherwise, at the end of the whole code return 0.

Categories