Checking for out of bounds in a 2D array - java

I'm trying to check the neighboring values of each element in a 2D array but am getting an IndexOutOfBoundsException when I reach the sides of the array or a corner. For example if my array is:
|2|4|2|7|8|
|8|1|0|5|6|
|0|3|1|5|2|
|1|9|7|2|0|
I know that all the neighbors of 8 are 7,5 and 6, but my if statements don't check the bounds properly. The code I have for this is:
int numOfRows = imageArray.length;
int numOfColumns = imageArray[0].length;
for(int i = 0; i < numOfRows; i++)
for(int j = 0; j < numOfColumns; j++)
if((j+1) < numOfColumns-1)
if((i+1) < numOfRows-1)
if((j-1) > 0 )
if((i-1) > 0 )
if((i+1) < numOfColumns-1 && (j+1) < numOfRows-1)
if((i-1) >= 0 && (j-1) >= 0)
if((i+1) < numOfColumns-1 && (j-1) >= 0)
if((i-1) >= 0 && (j+1) < numOfRows-1)
I've been working on this for a while and have gone through many different techniques to solve this. Any help would be great. Thanks.

If you're trying to get all the neighbor cells and do something with them, for example add them, then you need to do some sort of bounds checking, for example something modified from this could work:
for (int i = 0; i < numOfRows; i++) {
for (int j = 0; j < numOfCols; j++) {
// check all bounds out of range:
int iMin = Math.max(0, i - 1);
int iMax = Math.min(numOfRows - 1, i + 1);
int jMin = Math.max(0, j - 1);
int jMax = Math.min(numOfCols - 1, j + 1);
// loop through the above numbers safely
for (int innerI = iMin; innerI <= iMax; innerI++) {
for (int innerJ = jMin; innerJ <= jMax; innerJ++) {
if (i != innerI && j != innerJ) {
// do what needs to be done
}
}
}
}
}
Caveat: code has not been compiled nor tested and is mainly to show you the idea of what can be done rather than a copy-paste solution

Related

Pascal's triangle in Java [duplicate]

This question already has answers here:
Pascal's triangle positioning
(5 answers)
Closed 1 year ago.
Java beginner here! As part of practicing programming, I've run into Pascal's triangle. I tried to implement a solution where the triangle is printed like so:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
...
So roughly right-sided. My solution though runs into multiple errors, and although I would appreciate help with that, I would primarily like to know if I am thinking correctly with my solution. (For some functions I am using a custom library)
public static void main(String[] args) {
int input = readInt("Enter triangle size, n = ");
array = new int[input][input];
for (int i = 0; i < input; i++) { // rows
for (int j = 0; j < i + 1; j++) { // columns
if (i = 0) {
array[i][0] = 1;
} else if (i != 0 && i == j) {
array[i][j] = 1;
} else {
array[i][j] = array[i - 1][j] + array[i - 1][j - 1];
}
}
}
// print out only the lower triangle of the matrix
for (int i = 0; i < input; i++) {
for (int j = 0; j < input; j++) {
if (i <= j) {
System.out.println("%d ", array[i][j]);
}
}
}
}
You were on the right track. Here's how I implemented it:
Scanner sc = new Scanner(System.in);
System.out.print("Enter triangle size, n = ");
int n = sc.nextInt();
sc.close();
//This will be a jagged array
int[][] array = new int[n][0];
for (int i = 0; i < n; i++) {
//Add the next level (it's empty at the start)
array[i] = new int[i + 1];
for (int j = 0; j <= i; j++) {
//At the ends, it's just 1
if (j == 0 || j == i) {
array[i][j] = 1;
} else { //The middle
array[i][j] = array[i - 1][j - 1] + array[i - 1][j];
}
}
}
for (int i = 0; i < n; i ++) {
for (int j = 0; j <= i; j++) {
//printf is what you use to do formatting
System.out.printf("%d ", array[i][j]);
}
//Without this, everything's on the same line
System.out.println();
}
Your else part was correct, but you didn't check if j equaled 0 before that. Instead of setting the current element to 1 when i was 0 or when i equaled j, you should have done it when j was 0 or when i equaled j. Because of this mistake, in later rows where i was not 0, but j was, you tried to access array[i - 1][j - 1], which was basically array[i - 1][-1], causing an IndexOutOfBoundsException.
I also made a jagged array instead of an even matrix because it made more sense that way, but it shouldn't matter much.
Also, this wasn't an error, but you did else if (i!=0 && i==j) The i != 0 part is unnecessary because you checked previously if i == 0.
Link to repl.it

Magic Square gives ArrayIndexOutOfBoundException

I have been working on Magic Square formation, after reading through the algo, I found out there are certain set of rules to be followed while forming the MagicSquare.
The algo which I'm following is :
The magic constant will always be equal to n(n^2 + 1)/2, where n is the dimension given.
Numbers which magicSquare consists will always be equals 1 to n*n.
For the first element that is 1, will always be in the position (n/2, n-1).
Other elements will be placed like (i--,j++)
The condition to be put through for placing an elements are :
a) If i < 0, then i = n-1.
b) If j == n, then j = 0.
c) This is a special case, if i < 0 and j=n happens at the same time, then i = 0, j = n-2.
d) If the position is already occupied by some other element, then i++, j = j-2.
Then input the element inside the magicSquare based upon the conditions.
Based upon the above algo, I have written down a code, and due to some reason I'm getting
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at Main.generateMagicSquare(Main.java:25)
at Main.main(Main.java:58)
This is weird. I have checked, and feels like it is safe to use the code to get the desired result, but I don't know where I'm going wrong.
Code
static void generateMagicSquare(int n){
int[][] magicSquare = new int[n][n];
//initialising for pos of the elem 1
int i = n/2, j = n-1;
magicSquare[i][j] = 1;
//the element consist by the magic square will always be equal to 1 to n*n
for(int num=2; num <= n*n; num++){
//it must go like this, for any other element
i--; j++;
// if the element is already present
if(magicSquare[i][j] != 0){
i++;
j -= 2;
}else{
if(i < 0)
i = n-1;
if(j == n)
j = 0;
if(i < 0 && j == n){
i = 0;
j = n-2;
}
}
magicSquare[i][j] = num;
}
for(int k=0; k<n; k++){
for(int l=0; l<n; l++){
System.out.print(magicSquare[k][l] + " ");
}
System.out.println();
}
}
Any help would be appreciated. Thanks. Since I could have copied and pasted the code from internet, but I want to learn it in my way, and your help would help me achieve what I want. :)
EDITS
After reading through the exception, I made some amendments in my code, but still some of the result didn't come upto the mark.
Here is my updated code =======>
static void generateMagicSquare(int n){
int[][] magicSquare = new int[n][n];
//initialising for pos of the elem 1
int i = n/2, j = n-1;
magicSquare[i][j] = 1;
//the element consist by the magic square will always be equal to 1 to n*n
for(int num=2; num <= n*n; num++){
//it must go like this, for any other element
i--; j++;
if(i < 0){
i = n-1;
}
if(j == n){
j = 0;
}
if(i < 0 && j == n){
i = 0;
j = n-2;
}
if(magicSquare[i][j] != 0){
i++;
j -= 2;
}else{
magicSquare[i][j] = num;
}
}
for(int k=0; k<n; k++){
for(int l=0; l<n; l++){
System.out.print(magicSquare[k][l] + " ");
}
System.out.println();
}
}
I get this output :
2 0 6
9 5 1
7 3 0
Still not the right answer to follow.
This line throws the error:
if(magicSquare[i][j] != 0)
and the problem is that the array magicSquare is initialized as:
int[][] magicSquare = new int[n][n];
meaning that it has n columns with indexes from 0 to n - 1 (indexes are zero based).
The variable j is initialized as
j = n-1;
and later this line:
j++;
makes j equal to n
so when you access magicSquare[i][j] you are trying to access magicSquare[i][n] which does not exist.
The index of an array is an integer value that has value in interval [0, n-1], where n is the size of the array. If a request for a negative or an index greater than or equal to size of array is made, then the JAVA throws a ArrayIndexOutOfBounds Exception. You have to check the value of i and j before using it in array. You can use the below code :
for(int num=2; num <= n*n; num++){
i--; j++;
//Here We have to check the value of i and j i.e. it should less than or equal to the length of array.
if((i <= magicSquare[0].length-1 && j <= magicSquare[0].length-1))
{
if(magicSquare[i][j] != 0){
i++;
j -= 2;
}else{
if(i < 0)
i = n-1;
if(j == n)
j = 0;
if(i < 0 && j == n){
i = 0;
j = n-2;
}
}
magicSquare[i][j] = num;
}
}
For understanding ArrayIndexOutOfBoundsException, Please visit :
https://www.geeksforgeeks.org/understanding-array-indexoutofbounds-exception-in-java/

How can I find a local minimum in a 2D array?

public static void main(String[] args) {
// TODO code application logic here
int numRows = 5;
int numCols = numRows;
int[][] twoDimArray = new int[numRows][numCols];
Random randGen = new Random();
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++) {
int randIndex = randGen.nextInt(4);
int value = randGen.nextInt(100);
twoDimArray[i][j] = value;
}
}
System.out.println("\nThe two-dimensional array: ");
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++) {
System.out.print(twoDimArray[i][j] + " ");
}
System.out.println();
}
}
}
I want to find a local minimum using a "brute force" approach. I know with a one dimensional array I would use a for-loop to compare all the elements in the array until I found a local minimum, but I don't know how to do that here.
Edit: Could I use binary search instead? Find the middle row and search there and if one isn't found, I search one of the halves.
The brute force method would be very similar to that of a 1D array, just with an extra loop, and a few more checks:
public int[] findLocalMinimum(int[][] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
int current = arr[i][j];
if (i + 1 < arr.length && current >= arr[i + 1][j] ||
i - 1 >= 0 && current >= arr[i - 1][j] ||
j + 1 < arr[i].length && current >= arr[i][j + 1] ||
j - 1 >= 0 && current >= arr[i][j - 1]) {
continue;
} else {
return new int[] { i, j };
}
}
}
return new int[] { -1, -1 };
}

Make a square shape of asterisc around border of 2D Array

I am trying to fill with asterisks only the outside border of a 2D Array I have half of it done, but it seems that I cant get it to fill the last column and the last row in the 2D array.
so far I can do this
and here is my code:
for (int i = 0; i < array.length; i++)
{
for (int j = 0; j < array.length; j++)
{
if (array[i][j] == array[0][j] || array[i][j] == array[i][0])
{
array[i][j] = "*";
}
}
}
but obviously I want to finish the Square shape around the 2D array, so I tried something like this.
for (int i = 0; i < array.length; i++)
{
for (int j = 0; j < array.length; j++)
{
if (array[i][j] == array[array.length - 1][j]
|| array[i][j] == array[i][array.length - 1])
{
array[i][j] = "*";
}
}
}
My idea was just to go to the last valid position in the 2D array and simply print the column and the row but it doesn't seem to work. Thanks to all the help I can get, I really appreciate it as I'm a learner in Java.
#Ricki, your line of thinking was right, but what you didn't consider is that array[i][j] == array[array.length - 1][j] doesn't compare the "shell" per say, but the inner value of it, so, even if array[1][1] != array[2][1], if their values are null they are equals.
Try using this code:
int _i = 10;
int _j = 10;
String[][] array = new String[_i][_j];
for (int i = 0; i < _i; i++) {
for (int j = 0; j < _j; j++) {
if(i==0 || j == 0 || i == _i-1|| j == _j-1){
array[i][j] = "*";
}
}
}
What i've done is comparing the first row (i==0), the first column (j==0), the last row (i == _i-1) and the last column (j == _j-1).
And then:
**********
* *
* *
* *
* *
* *
* *
* *
* *
**********
you can do something likewise,
public static void main(String[] args) {
int n = 5;
String [][] array = new String[n][n]; // 2-dimension array define...
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
if(i == 0 || (i == array.length-1 || j==0 || j==array.length-1)){ // if top,left,right,bottom line then this...
array[i][j] = "*|";
}else{ // if not border line then this...
array[i][j] = "_|";
}
}
}
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
System.out.print(array[i][j] + " ");
}
System.out.println("");
}
}
OUTPUT :

Minesweeper game blocks around the mines

Hi so I'm building a program to create the classical minesweeper game in Java, and have almost everything down but I cant figure out how to check the sqaures around a mine and to write in the numbers (i.e. if there are one, two, three mines next to it). I only included the method it's under, but I can post the rest of the program if necessary. What should my approach be? Thanks!
private void countAdjacentMines()
{
for (int i = 0; i < mineField.length; i++)
{
for (int j = 0; j < mineField.length; j++)
{
if (!(mineField[i][j].getIsMine()))
{
mineField[i-1][j-1];
mineField[i-1][j];
mineField[i-1][j+1];
mineField[i][j-1];
mineField[i][j+1];
mineField[i+1][j-1];
mineField[i+1][j];
mineField[i+1][j+1];
mineField[i][j].setAdjacentMines(0);
}
} // end for loop rows
} // end for loop columns
} // end countAdjacentMines
Something like this:
private void countAdjacentMines()
{
for (int i = 0; i < mineField.length; i++)
{
for (int j = 0; j < mineField.length; j++)
{
if (!(mineField[i][j].getIsMine()))
{
int count = 0;
for (int p = i - 1; p <= i + 1; p++)
{
for (int q = j - 1; q <= j + 1; q++)
{
if (0 <= p && p < mineField.length && 0 <= q && q < mineField.length)
{
if (mineField[p][q].getIsMine())
++count;
}
}
}
mineField[i][j].setAdjacentMines(count);
}
} // end for loop rows
} // end for loop columns
} // end countAdjacentMines
For each item in that "list", do something like:
if ((i-1) >= 0 && (j-1) >= 0 && mineField[i-1][j-1].getIsMine()) {
numAdjacentMines++;
}
It's probably worth writing a helper function to do all of this, and then you just need to call it 8 times.
You're on the right track. You should be keeping a counter, that represents the count of adjacent mines that return true for .getIsMine().
if (!(mineField[i][j].getIsMine()))
{
counter = 0;
if (i-1 >= 0)
{
if (j-1 >=0 && mineField[i-1][j-1].getIsMine()) counter++;
if (mineField[i-1][j].getIsMine()) counter++;
if (j+1 < mineField.length && mineField[i-1][j+1].getIsMine()) counter++;
}
if (j-1 >=0 && mineField[i][j-1].getIsMine()) counter++;
if (j+1 < mineField.length && mineField[i][j+1].getIsMine()) counter++;
if (i+1 < mineField.length)
{
if (j-1 >=0 && mineField[i+1][j-1].getIsMine()) counter++;
if (mineField[i+1][j].getIsMine()) counter++;
if (j+1 < mineField.length && mineField[i+1][j+1].getIsMine()) counter++;
}
mineField[i][j].setAdjacentMines(counter);
}
You also need to be checking that all of those values (i-1, j-1, i+1, j+1) don't go outside the bounds of your array (i - 1 > -1, etc)
EDIT:: I think I covered all of the checks.
I'm not sure what you're trying to do. This statement, mineField[i-1][j-1]; and the ones like it just access data and do nothing with it.
I'm assuming that the array stores something that includes a boolean that tells you whether or not there's a mine in that space. If that's true, just make a counter and change those statements to something like if(mineField[i-1][j-1].hasMine()) counter++;. And then change the last statement to mineField[i][j].setAdjacentMines(counter);.
int sum = 0;
sum += mineField[i-1][j-1].getIsMine() ? 1 : 0;
sum += mineField[i-1][j].getIsMine() ? 1 : 0;
sum += mineField[i-1][j+1].getIsMine() ? 1 : 0;
sum += mineField[i][j-1].getIsMine() ? 1 : 0;
sum += mineField[i][j+1].getIsMine() ? 1 : 0;
sum += mineField[i+1][j-1].getIsMine() ? 1 : 0;
sum += mineField[i+1][j].getIsMine() ? 1 : 0;
sum += mineField[i+1][j+1].getIsMine() ? 1 : 0;
mineField[i][j].setAdjacentMines(sum);
This is count up how many are mines and use it properly. It may be more clean to create a loop to perform this calculation, since it is the same thing for each adjacent field.
Try something like:
private static int countAdjacentMines(int x, int y) {
int adjacentMines = 0;
for(int i = -1; i <= 1; i++) {
if((x + i < 0) || (x + i >= width)) {
continue;
}
for(int j = -1; j <= 1; j++) {
if((y + j < 0) || (y + j >= height)) {
continue;
}
if(mineField[x + i][y + j].getIsMine()) {
adjacentMines++;
}
}
}
return adjacentMines;
}
This should count the number of mines neighbouring a block at (x, y).

Categories

Resources