16

I have a series of if statements, as shown below:

if (board[x+1][y]==true) {
    ar+=1;
}
if (board[x][y+1]==true) {
    ar+=1;
}
if (board[x-1][y]==true) {
    ar+=1;
}
if (board[x][y-1]==true) {
    ar+=1;
}
if (board[x+1][y+1]==true) {
    ar+=1;
}
if (board[x+1][y-1]==true) {
    ar+=1;
}
if (board[x-1][y+1]==true) {
    ar+=1;
}
if (board[x-1][y-1]==true) {
    ar+=1;
}

Is there a way to simplify/condense these statements with Java?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Eragon20
  • 483
  • 1
  • 7
  • 20
  • 41
    `== true` is redundant. You do not need it. – OneCricketeer Nov 28 '16 at 04:50
  • 6
    Perhaps you are searching for the `switch` statement? Also, are you writing battleship? – Ashwin Gupta Nov 28 '16 at 04:51
  • 1
    I considered the `switch` statement, but that's only if you're comparing one variable, so I didn't see how I could apply that here. Also, this code is for a visual Conway's Game of Life simulation, but good guess! – Eragon20 Nov 28 '16 at 04:53
  • @HanletEscaño nope, more than one could be true in which case more than one should be added – Jeremy Kahan Nov 28 '16 at 04:53
  • 1
    @HanletEscaño That wouldn't work. `ar` needs to increment for **each** time one is `true`. Notice that they aren't `else if` statements. – 4castle Nov 28 '16 at 04:54
  • @EugeneRyabtsev Can you add boolean values in Java as though they were integers? I thought you can't. – Ari Brodsky Nov 28 '16 at 10:23
  • I think your question would be better in [CodeReview.SE]. – Soner Gönül Nov 28 '16 at 10:44
  • 4
    This must be a duplicate of something, right? *Right?* – Mast Nov 28 '16 at 10:46
  • 3
    @SonerGönül In it's current form, it would be closed for lacking context. Code Review is about improving existing, working code. The code posted here is not reviewable in this form because it leaves us guessing at the author's intentions. Unlike Stack Overflow, Code Review needs to look at concrete code in a real context. Please see [Why is hypothetical example code off-topic for CR?](http://meta.codereview.stackexchange.com/q/1709/41243) – Mast Nov 28 '16 at 10:49
  • @Mast Fair enough :) – Soner Gönül Nov 28 '16 at 10:53
  • I'd consider separating checking the board contents from enumerating the neighbours. – CodesInChaos Nov 28 '16 at 13:36

6 Answers6

42

Simply loop around the position that you care about. Skipping the center of the "box".

Tip: You access a 2D array by row then column, or [y][x] (at least, that's how you'd translate the board from looking at the code).

// int x, y;  // position to look around 
for (int xDiff = -1; xDiff <= 1; xDiff++) {
    for (int yDiff = -1; yDiff <= 1; yDiff++) {
        if (xDiff == 0 && yDiff == 0) continue;
        if (board[y+yDiff][x+xDiff]) { 
            ar += 1;
        }
    }
}

Beware - Out of bounds exception is not handled

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
13

The following would be a more visual equivalent, easily extensible to other shapes of the area of interest. Note ternary operators, ?: which are necessary in Java to convert bools to ints.

ar += (board[x-1][y-1]?1:0) + (board[x-1][y]?1:0) + (board[x-1][y+1]?1:0);
ar += (board[x+0][y-1]?1:0) +                       (board[x+0][y+1]?1:0);
ar += (board[x+1][y-1]?1:0) + (board[x+1][y]?1:0) + (board[x+1][y+1]?1:0);
Eugene Ryabtsev
  • 2,232
  • 1
  • 23
  • 37
  • although this ain't, arguably, the best way to do it (can't extrapolate it easily to bigger board sizes, can be suboptimal in languages where ternaries are evaluated at runtime exclusively etc.), +1 for the freshness of the very idea of grouping them visually depending on coords. –  Nov 28 '16 at 16:52
  • 3
    Maybe change to a helper function `get(board, x-1, y-1)` so that you don't need to repeat the ternary, and also can add bounds checking easily. – Bergi Nov 28 '16 at 18:05
10

In addition to the answers you already have, you can also use enhanced for loops (and re-use the range as it is the same for both).

int[] range = { -1, 0, 1 };
for (int i : range) {
  for (int j : range) {
    if ((i != 0 || j != 0) && board[i][j])  { 
      ar++;
    }
  }
}
Eddie Curtis
  • 1,207
  • 8
  • 20
8

This code should give the same result (probably you want to check that you are always in the bounds of the matrix

for(int i=-1; i<=1; i++) {
   for(int j=-1; j<=1; j++) {
        if((i != 0 || j != 0) && board[x+i][y+j]) {
           ar++;
        }
   }
}
Mikel San Vicente
  • 3,831
  • 2
  • 21
  • 39
5

You can simplify as follows as well :

for(int i = x-1;i<=x+1;i++) {
    for(int j=y-1;j<=y+1;j++) { 
        if(i==x && j==y) continue;
        if (board[i][j]) {
           ar+=1;
        }
    }
}
Naman
  • 27,789
  • 26
  • 218
  • 353
  • This can be shortened further to a single line: `for (int i=x-1;i<=x+1;i++) for (int j=y-1;j<=y+1;j++) if ((i!=x || j!=y) && board[i][j]) ar+=1;` – SunKnight0 Nov 28 '16 at 15:46
4

Looks like you're testing surrounding squares apart from (x, y) itself. I'd use a loop to maintain a counter, with extra step to exclude the (x, y) centre cell.

for (int xTest = x - 1; xTest <= x + 1; xTest++) {
    for (int yTest = y - 1; yTest <= y + 1; yTest++) {
        if (xTest == x && yTest == y) {
            continue;
        }
        if (board[xTest][yTest]) {
            ar += 1;
        }
    }           
}

Also, note the == true is unnecessary. Boolean statements are first class citizens in Java.

Adam
  • 35,919
  • 9
  • 100
  • 137