How to find specific neighbors in a two-dimensional array - java

I have an exercise where I have a 2D array in Java. I take user input, a String, that looks something like "F3 F7" and I mark the coordinates given on the array. Please see below picture.
2DArray
My problem is the fact that I need to check the neighbors of the input to make sure that future inputs do not touch (neither vertically, nor horizontally).
I found the below code in a post here, but I simply do not have the inspiration on how to implement it in order to check only for a specific set in the array.
for (i = 0; i < array.length; i++) {
for (j = 0; j < array[i].length; j++) {
for (x = Math.max(0, i - 1); x <= Math.min(i + 1, array.length); x++) {
for (y = Math.max(0, j - 1); y <= Math.min(j + 1,
array[i].length); y++) {
if (x >= 0 && y >= 0 && x < array.length
&& y < array[i].length) {
if(x!=i || y!=j){
System.out.print(array[x][y] + " ");
}
}
}
}
System.out.println("\n");
}
}

Related

Implementing flood fill to check for group - Java

I have been looking over this flood fill implementation for some time now and keep running into the dreaded stack overflow. I am dropping pieces randomly on a 12x10 grid and calling the checkMatches method after each random piece drop to check for groups of three or more, hence the flood fill use.
EDIT: See comment
public void checkMatches(int x, int y, int type)
{
if (x < 0 || x >= PIECES_WIDE || y < 0 || y >= PIECES_TALL || type == 0)
return;
if (grid[x][y].getType() != type)
return;
int checkL = x;
while (checkL >= 0 && grid[checkL][y].getType() == type)
{
grid[checkL][y].setDestroy(true);
numMatches++;
checkL--;
}
checkL++;
int checkR = x;
while (checkR < PIECES_WIDE - 1 && grid[checkR][y].getType() == type)
{
grid[checkR][y].setDestroy(true);
numMatches++;
checkR++;
}
checkR--;
for (int i = checkL; i <= checkR; i++)
{
if (y > 0 && grid[i][y - 1].getType() == type)
checkMatches(i, y - 1, type);
if (y < PIECES_TALL - 1 && grid[i][y + 1].getType() == type)
checkMatches(i, y + 1, type);
}
}
Then the relevant code to call the method and destroy the pieces if there have been three matched pieces:
checkMatches(x, y, type);
if (numMatches >= 3)
{
for (int i = 0; i < PIECES_WIDE; i++)
{
for (int j = 0; j < PIECES_TALL; j++)
{
if (grid[i][j].isDestroy())
destroyPiece(grid[i][j]);
}
}
} else
{
numMatches = 0;
for (int i = 0; i < PIECES_WIDE; i++)
{
for (int j = 0; j < PIECES_TALL; j++)
{
grid[i][j].setDestroy(false);
}
}
}
My eyes and brain hurt. I know that the recursion is causing the overflow, but I also know that this implementation is possible in some form. Therefore I'm doing something wrong. Thanks in advance.
You need to put a mark on the pieces that you have already found matching. Then you can make a loop to extend your matchings, until you notice that no more pieces have been marked. Then you can stop.

Android Minesweeper algorithm

I'm developing a game "Minesweeper" for Andoid on Java and I have a problem when opening the cells. How to make sure that I click on the cell opened adjacent empty cells? (How it is done in Miner for Windows).
Introduction: I have an array which i receive from bluetooth socket stream. Array like this :
1 9 1 0
1 1 1 0
0 0 0 0
0 0 0 0
9-is a mine
0-is blank cell
1-nearest mines count
After that i calculate game field
array = Model.getGameField();
int size = array.length;
for (int i = 0; i < size; i++)
for (int j = 0; j < size; j++)
{
((TableRow) table.getChildAt(i)).getChildAt(j).setTag(array[i][j] + "");
}
OnClick function :
if (iWantToSetFlag == 0)
{
tmpBtn = ((Button) v);
if (!(tmpBtn.getTag().equals("9")))
{
OpenButtons(tmpBtn.getId() / 10, tmpBtn.getId() % 10);
recreateTable();
}
else
startLose();
}
else
{
if (((Button) v).getText().equals("M"))
((Button) v).setText("");
else
((Button) v).setText("M");
}
I have a function
private void OpenButtons(int x, int y)
{
array[x][y] = -1;
for (int k = -1; k < 2; k++)
{
for (int k1 = 1; k1 >= -1; k1--)
{
if (x + k >= 0 && x + k < array.length && y - k1 >= 0 && y - k1 < array[x + k].length)
if (array[x + k][y - k1] == 0)
OpenButtons(x + k, y - k1);
}
}
}
which recursively open cells but i have a StackOverFlow error. Help please.
You should be calling your recursion with changed parameters:
if (array[x + k][y - k1] == 0)
OpenButtons(x + k, y - k1);
And of course, as has been mentioned in the comments of the question, you should check for the array bounds yourself instead of just ignoring the exceptions:
if (x + k >= 0 && x + k < array.length &&
y - k1 >= 0 && y - k1 < array[x + k].length) { ...
put before your other if-clause will only check fields which actually exist. Ridding you of your malicious empty try-catch.
Since the recursive algorithm will still cause a StackOverflowException for large fields, an iterative algorithm might be better suited here.
private void OpenButtons(int x, int y) {
Queue<Point> toOpen = new LinkedBlockingQueue<>();
toOpen.add(new Point(x, y));
array[x][y] = -1;
while (!toOpen.isEmpty()) {
Point p = toOpen.poll();
x = p.x;
y = p.y;
for (int k = -1; k < 2; k++) {
for (int k1 = 1; k1 >= -1; k1--) {
if (x + k >= 0 && x + k < array.length && y - k1 >= 0
&& y - k1 < array[x + k].length)
if (array[x + k][y - k1] == 0) {
array[x + k][y - k1] = -1;
toOpen.add(new Point(x + k, y - k1));
}
}
}
}
}

My assignment is to make a house using for loops. The house should look like this

*
*****
*********
*********
**** ***
**** ***
so far i only have this
for (int i=1; i<10; i += 4)
{
for (int j=0; j<i; j++)
{
System.out.print("*");
}
System.out.println("");
}
}
}
The simplest decision will be:
for (int y = 0; y < 6; y++) {
int shift = y < 2 ? 4 / (y + 1) : 0;
for (int x = 0; x < 9 - shift; x++) System.out.print(x >= shift && (y < 4 || (x < 4 || x > 5)) ? "*" : " ");
System.out.println();
}
I think Andre's answer is the most concise one, but if you want to have configurable home building you can use next one(try to change HEIGHT/WIDTH to see effect):
public class House {
public static void main(String[] args) {
final int HEIGHT = 6;
final int WIDTH = 9;
for (int i = 0; i < HEIGHT * 2; i += 2) {
for (int j = 0; j < WIDTH; j++) {// check for roof
if ((i + (i % 2) + (WIDTH) / 2) < j // right slope
|| (i + (i % 2) + j) < (WIDTH) / 2)// left slope
{
System.out.print(" ");
} else {
if ((i / 2 >= HEIGHT * 2 / 3) && (j >= WIDTH / 2) && j < WIDTH / 2 + HEIGHT / 3) {// check for door
System.out.print(" ");
} else {// solid then
System.out.print("*");
}
}
}
System.out.println();
}
}
}
EDIT - answer to comment:
Try to run next two example and compare output:
public static void main(String[] args) {
final int SIZE = 9;
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
System.out.print(i < j ? "+" : "-");
}
System.out.println();
}
}
and
public static void main(String[] args) {
final int SIZE = 9;
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
System.out.print(i < SIZE - j - 1 ? "+" : "-");
}
System.out.println();
}
}
First one will give you right slope and second left one. It all come from geometric properties of points. In first case all points will have bigger value on on x axis than on y axis. In second both x and y in sum won't exceed SIZE.
You can try to modify boolean expression inside of if() statement and see what happens, but I'd encourage you to get piece of paper and try to play with paper and pen and see what properties certain points have. Let me know if you need more explanation.
You could use a two-dimensional array like this:
char matrice [][]= {{' ',' ',' ',' ' '*', ' ',' ',' ',' '},
{' ',' ','*','*', '*', '*','*',' ',' '}};
(And so on). You basically draw your house using your array indexes.
Now you can parse each line using System.out.print() when you have to print a character, and System.out.println("") between each row.
It would look like this:
for(char[] line : house){
for(char d : line){
System.out.print(d);
}
System.out.println("");
}
You should take a look at the for-each statement documentation if you're not familiar with it.

Find elements surrounding an element in an array

I have a multidimensional array, I want to get the elements surrounding a particular element in that array.
For example if I have the following:
[[1,2,3,4,5,6]
[8,9,7,5,2,6]
[1,6,8,7,5,8]
[2,7,9,5,4,3]
[9,6,7,5,2,1]
[4,7,5,2,1,3]]
How do I find all the 8 elements around any of the above elements? And how do I take care of elements at the edges?
One way I figured out is, to write a 9 line code for this , which is obvious, but is there a better solution?
You can use 'direction array' in form
[[-1,-1], [-1,0],[1,0]..and so on]
And method which takes point coordinate and iterates through direction array -> add direction numbers to coordinates, check indexes are not out of bounds and collect results.
Something like this:
private static int[][] directions = new int[][]{{-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0, -1}};
static List<Integer> getSurroundings(int[][] matrix, int x, int y){
List<Integer> res = new ArrayList<Integer>();
for (int[] direction : directions) {
int cx = x + direction[0];
int cy = y + direction[1];
if(cy >=0 && cy < matrix.length)
if(cx >= 0 && cx < matrix[cy].length)
res.add(matrix[cy][cx]);
}
return res;
}
For (i, j) ->
(i - 1, j - 1)
(i - 1, j)
(i - 1, j + 1)
(i, j - 1)
(i, j + 1)
(i + 1, j - 1)
(i + 1, j)
(i + 1, j + 1)
Now, at the edges, you can check for num % row == 0, then its at row edge...
and , num % col == 0 then its column edge..
Here's is how you can proceed: -
Given an index (i, j).. You can find elements in a rows adjacent to j for i - 1, then i, and then i + 1. (NOTE : - for index i you just have to access j - 1, and j + 1)
Subsequently you also can check for the row edge and column edge..
Here, you can look at the code below, how it can happen: -
// Array size
int row = 6;
int col = 6;
// Indices of concern
int i = 4;
int j = 5;
// To the left of current Column
int index = i - 1;
for (int k = -1; k < 2; k++) {
if (index % row > 0 && ((j + k) % col) > 0) {
System.out.println(arr[index][j + k]);
}
}
// In the current Column
index = i;
// Increment is 2 as we don't want (i, j)
for (int k = -1; k < 2; k = k + 2) {
if (index % row > 0 && ((j + k) % col) > 0) {
System.out.println(arr[index][j + k]);
}
}
// To the right of current Column
index = i + 1;
for (int k = -1; k < 2; k++) {
if (index % row > 0 && ((j + k) % col) > 0) {
System.out.println(arr[index][j + k]);
}
}
UPDATE : - The above code can further be simplified.. But I leave that task to you..
HINT: - You can reduce one for loop from there..
for (i = 0; i < array.length; i++) {
for (j = 0; j < array[i].length; j++) {
for (x = Math.max(0, i - 1); x <= Math.min(i + 1, array.length); x++) {
for (y = Math.max(0, j - 1); y <= Math.min(j + 1,
array[i].length); y++) {
if (x >= 0 && y >= 0 && x < array.length
&& y < array[i].length) {
if(x!=i || y!=j){
System.out.print(array[x][y] + " ");
}
}
}
}
System.out.println("\n");
}
}
Thanks to all the people who have answered, but i figured it out with the help of this post which i found just now, and above is the solution. thanks again :)
Base case is just to obtain neighbour elements by indexing shifting. For (i,j) it will be (i + 1, j), (i - 1, j), etc.
On the edges I use two approaches:
Modulo % operator to avoid IndexOutOfBounds exception, but it sometimes confuse with wrong elements indexation.
Wrap your matrix with one layer of default elements. It adds some extraspace for holding matrices, but makes your code more readable without catching exception, lot ifs and so on. This trick often used when representation maze as matrix.
Example: your default element is 0.
0 0 0 0 0 0
0 1 2 3 4 0
0 2 6 7 3 0
0 1 3 5 7 0
0 2 4 6 2 0
0 0 0 0 0 0
Note: do not forget iterate through actual array size, not extended.
This is my solution for your problem written in Ruby. Instead of calculating if element is at edge you could access elements "over" the edge and handle "nil" values or exceptions that happen there. Then remove "nil" values from final list. This solution is not as good as calculating if some "point" is over the edge or not.
big_map = [[1,2,3,4,5,6],
[8,9,7,5,2,6],
[1,6,8,7,5,8],
[2,7,9,5,4,3],
[9,6,7,5,2,1],
[4,7,5,2,1,3]]
# monkey patch classes to return nil.
[NilClass, Array].each do |klass|
klass.class_eval do
def [](index)
return nil if index < 0 or index > self.size rescue nil
self.fetch(index) rescue nil
end
end
end
class Array
# calculate near values and remove nils with #compact method.
def near(i,j)
[ self[i - 1][j - 1], self[i - 1][j - 0], self[i - 1][j + 1],
self[i - 0][j - 1], self[i - 0][j + 1],
self[i + 1][j - 1], self[i + 1][j - 0], self[i + 1][j + 1],
].compact
end
end
puts big_map.near(1,1).inspect
# => [1, 2, 3, 8, 7, 1, 6, 8]
puts big_map.near(0,0).inspect
# => [2, 8, 9]
puts big_map.near(5,5).inspect
# => [2, 1, 1]
I was working on he same problem and came up with a small optimized solution to find the surrounding numbers of any point in a 2D matrix, hope this helps, please comment if I can shorten the logic somehow
Code:-
import java.util.ArrayList;
public class test {
public static void main(String[] arg){
int[][] arr = {{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15},{16,17,18,19,20},{21,22,23,24,25}};
//int[][] arr = {{width,2,3},{4,5,6},{7,8,9}};
ArrayList<Integer> al = new ArrayList<Integer>();
int x = 2, y = 2;
int width = 2; //change the value of width, according to the requirement
for(int i = 0; i < 5; i++){
for(int j = 0; j < 5; j++){
if( (i == (x-width) && ( (y+width) >= j && j >= (y-width))) || (i == (x+width) && ( (y+width) >= j && j >= (y-width))) || (j == (y-width) && ( (x+width) >= i && i >= (x-width))) || (j == (y+width) && ( (x+width) >= i && i >= (x-width))) ){
//if( x >= 0 && i < (i+width) && y >= 0 && j < (j+width))
{
al.add(arr[i][j]);
}
}
}
}
System.out.println(al);
}
}
You didnt mention if you want cyclical neighbours for edges or ignores cyclical neighbours. Assuming you want cyclical neighbours here is the code,
List<Integer> getNeighbours(int[][] mat, int x, int y){
List<Integer> ret = new ArrayList<Integer>();
int rows = mat.length;
int cols = mat[0].length;
for(int i=-1,i<=1;i++)
for(int j=-1;j<=1;j++)
if(i||j) ret = ret.add(mat[(x+i)%rows][(y+j)%cols]);
return ret;
}
(x-1, y-1) -> upper left
(x-1, y) -> left
(x-1, y+1) -> lower left
(x, y+1) -> up
(x, y) -> current position
(x, y-1) -> down
(x+1, y+1) -> upper right
(x+1, y) -> right
(x+1, y-1) -> lower right
You can use this as guide. Now all you need to do is add them in a try catch.
for( int x=0; x<arr.length; x++ ){
for(int y=0; y<arr[x].length; y++){
if( arr[x][y] == 8 ){
try{
System.out.println("Upper Left is: " + arr[x-1][y-1]);
}catch(ArrayIndexOutOfBoundsException e){
//do something
}
try{
System.out.println("Left is: " + arr[x-1][y]);
}catch(ArrayIndexOutOfBoundsException e){
//do something
}
//.....and others
}
}

Output an ASCII diamond shape using loops

I am trying to write a program in Java that captures an integer from the user (assume data is valid) and then outputs a diamond shape depending on the size of the integer, i.e. User enters 5, output would be:
--*--
-*-*-
*---*
-*-*-
--*--
So far I have:
if (sqr < 0) {
// Negative
System.out.print("#Sides of square must be positive");
}
if (sqr % 2 == 0) {
// Even
System.out.print("#Size (" + sqr + ") invalid must be odd");
} else {
// Odd
h = (sqr - 1) / 2; // Calculates the halfway point of the square
// System.out.println();
for (j = 0; j < sqr; j++) {
for (i = 0; i < sqr; i++) {
if (i != h) {
System.out.print(x);
} else {
System.out.print(y);
}
}
System.out.println();
}
}
Which just outputs:
--*--
--*--
--*--
--*--
--*--
I was thinking about decreasing the value of h but that would only produce the left hand side of the diamond.
void Draw(int sqr) {
int half = sqr / 2;
for (int row = 0; row < sqr; row++) {
for (int column = 0; column < sqr; column++) {
if ((column == Math.abs(row - half))
|| (column == (row + half))
|| (column == (sqr - row + half - 1))) {
System.out.print("*");
} else {
System.out.print("_");
}
}
System.out.println();
}
}
Ok, now this is the code, but as I saw S.L. Barth's comment I just realised this is a homework. So I strongly encourage you to understand what is written in this code before using it as final. Feel free to ask any questions!
Take a look at your condition:
if (i != h)
This only looks at the column number i and the midway point h.
You need a condition that looks at the column number and the row number. More precisely, you need a condition that looks at the column number, the row number, and the distance of the column number from the midway point.
Since this is a homework question, I leave determining the precise formula to you, but I'm willing to drop some more hints if you need them. Good luck!
You can use two nested for loops from -h to h, where h is half a diamond. The edge of a diamond is obtained when:
Math.abs(i) + Math.abs(j) == h
If user input n=5, then h=2, and a diamond looks like this:
n=5, h=2
--*--
-*-*-
*---*
-*-*-
--*--
Try it online!
// user input
int n = 9;
// half a diamond
int h = n / 2;
// output a diamond shape
System.out.println("n=" + n + ", h=" + h);
for (int i = -h; i <= h; i++) {
for (int j = -h; j <= h; j++) {
if (Math.abs(i) + Math.abs(j) == h) {
System.out.print("*");
} else {
System.out.print("-");
}
}
System.out.println();
}
Output:
n=9, h=4
----*----
---*-*---
--*---*--
-*-----*-
*-------*
-*-----*-
--*---*--
---*-*---
----*----

Categories