Checking for neighbours more elegantly in Conway's Game of Life
You're right, there's an alternate way to do this, but, first, some Java standards:


1-liners should have braces. This is a code-style that is common to many langauges because it is more maintainable, and leads to fewer future bugs. Lines like:


if (x &lt; 0 || y &lt; 0 || x &gt; getWidth() - 1 || y &gt; getHeight() -1) return;



should be:

if (x &lt; 0 || y &lt; 0 || x &gt; getWidth() - 1 || y &gt; getHeight() -1) {
    return;
}

Don't use arithmetic when you can use a simpler operator. Back to:


if (x &lt; 0 || y &lt; 0 || x &gt; getWidth() - 1 || y &gt; getHeight() -1) { ... }



Which can be simplified to:

if (x &lt; 0 || y &lt; 0 || x &gt;= getWidth() || y &gt;= getHeight()) { ...}

Use plain booleans when they make sense (again, back to...):


if (x &lt; 0 || y &lt; 0 || x &gt;= getWidth() || y &gt;= getHeight()) { ...}



which can be put in a function like (transformed to uses &amp;&amp; instead):

public boolean getTile(int x, int y) {
    return x &gt;= 0 &amp;&amp; y &gt;= 0 &amp;&amp; x &lt; getWidth() &amp;&amp; y &lt; getHeight() &amp;&amp; tile[y][x];
}


Note, how the standard boolean short-circuit evaluation ensures that the x and y are valid before the tile[y][x] is used.


OK, about that code duplication. A trick with these sorts of problems is to use an array of offsets. Consider your grid, which has 8 neighbours (in a relative y,x format):

-1,-1     -1,0    -1,+1

 0,-1     *us*     0,+1

+1,-1     +1,0    +1,+1


We can put these neighbour offsets in to an array:

private static final int[][] NEIGHBOURS = {
    {-1, -1}, {-1, 0}, {-1, +1},
    { 0, -1},          { 0, +1},
    {+1, -1}, {+1, 0}, {+1, +1}};


Then, your check method becomes:

static int countNeighbours(Board b, int x, int y) {
    int cnt = 0;
    for (int[] offset : NEIGHBOURS) {
        if (b.getTile(x + offset[1], y + offset[0]) {
           cnt++;
        }
    }
    return cnt;
 }