HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Flood-clearing routine for a JavaFx Minesweeper

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
routineclearingfloodforjavafxminesweeper

Problem

I really hate copy and pasting my code from one method to another. It signals something in my brain, "This could be done either more efficiently or more readable". This is used in a minesweeper program I am implementing with a JavaFx GUI (that's not very relevant, but it might help to know). Hopefully this is enough context!

```
@Contract(pure = true)
private int setMinX(int x){ return (x == 0 ? 0:(x-1)); }
@Contract(pure = true)
private int setMinY(int y){ return (y == 0 ? 0:(y-1)); }
@Contract(pure = true)
private int setMaxX(int x){ return (x == this.width-1 ? this.width-1 : x+1); }
@Contract(pure = true)
private int setMaxY(int y){ return (y == this.height-1 ? this.height-1 : y+1);}

private void adjacents(int x, int y){
//calculate adjacents for the just placed mine
int minX = setMinX(x);
int minY = setMinY(y);
int maxX = setMaxX(x);
int maxY = setMaxY(y);

if (this.mineField[minX][minY] != -1){ this.mineField[minX][minY] += 1; } //left top corner
if (this.mineField[maxX][minY] != -1){ this.mineField[maxX][minY] += 1; } //right top corner
if (this.mineField[maxX][maxY] != -1){ this.mineField[maxX][maxY] += 1; } // bottom right corner
if (this.mineField[minX][maxY] != -1){ this.mineField[minX][maxY] += 1; } // bottom left corner

if(x > 0 && x 0 && y = 0 && !this.liveGame[x][y]) {
//IMPLEMENT WITH GUI
//show(x,y);
if (this.mineField[minX][minY] == 0) {
floodClear(minX, minY);
}
if (this.mineField[maxX][minY] == 0) {
floodClear(maxX, minY);
}
if (this.mineField[maxX][maxY] == 0) {
floodClear(maxX, maxY);
}
if (this.mineField[minX][maxY] == 0) {
floodClear(minX, maxY);
}

if (x > 0 && x 0 && y < this.height - 1) {
if (this.mineField[minX][y] == 0) {
floodClear(minX, y);
} // left-middle
if (this.mineField[maxX][y] == 0) {

Solution

Iterating through adjacents

There are two main approaches to take while iterating through the neighbors in Minesweeper.

The first and most common option is to use a nested for loop:

for (int y = -1; y <= 1; y++) {
    for (int x = -1; x <= 1; x++) {
        if (x == 0 && y == 0) {
            continue; // We don't want to consider the field itself as a neighbor
        }
        increaseAdjacentMineCounter(mineX + x, mineY + y);
    }
}


The second approach, and the one that I normally use and like better, is to use an array to define which fields should be used as your neighbors.

int[][] neighbors = {{ -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 },
    { 0, 1 }, { 1, -1 }, { 1, 0 }, { 1, 1 }};
for (int[] neighbor : neighbors) {
    int x = neighbor[0];
    int y = neighbor[1];
    increaseAdjacentMineCounter(mineX + x, mineY + y);
}


The reason for why I like the second approach better is because it becomes more data-oriented. You can change the way you consider neighbors without changing your code. Changing the way your neighbors are considered can be a bit entertaining but very confusing :)

Code Snippets

for (int y = -1; y <= 1; y++) {
    for (int x = -1; x <= 1; x++) {
        if (x == 0 && y == 0) {
            continue; // We don't want to consider the field itself as a neighbor
        }
        increaseAdjacentMineCounter(mineX + x, mineY + y);
    }
}
int[][] neighbors = {{ -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, -1 },
    { 0, 1 }, { 1, -1 }, { 1, 0 }, { 1, 1 }};
for (int[] neighbor : neighbors) {
    int x = neighbor[0];
    int y = neighbor[1];
    increaseAdjacentMineCounter(mineX + x, mineY + y);
}

Context

StackExchange Code Review Q#133125, answer score: 2

Revisions (0)

No revisions yet.