polarBody wrote:I have a few questions. What do the isEmpty() and isWrapper() methods of the MButton class do? I would guess that isWrapper() returns whether the button is adjacent to a mine, but I can't think what isEmpty() does.
It is best, for a minesweeper game (in my opinion) to create a N+2 by M+2 array where N and M are the specified width and height. The wrapper consists of buttons that aren't even visible, they just provide an easier way for counting mines around a cell. The isEmpty() method simply checks if the cell is empty or not (if it has no adjacent bombs or not). So, I named it isEmpty() since there isn't anything contained inside of it (such as a bomb or a 1, 2, ...,
.
I spotted the mistake in adding cells into the queue just after I left the lab (I had to go to class, so I couldn't edit it). I was adding cells that were not yet revealed, but would be revealed when it was their turn to be removed from the queue. Hence, I modified my code a bit. Here is the modified version:
Code: Select all
public void floodFill(int row, int col) {
Queue<MButton> q = new LinkedList<MButton>();
if (!board[row][col].isEmpty())
return;
q.add(board[row][col]);
MButton mb;
while(!q.isEmpty()) {
mb = q.remove();
if (!mb.isRevealed()) {
mb.reveal();
numSafeSpots--;
if (numSafeSpots == 0)
win();
}
if (!mb.isEmpty())
continue;
row = mb.rowPosition();
col = mb.colPosition();
if (!board[row-1][col].isRevealed() && !board[row-1][col].isWrapper()) {
q.add(board[row-1][col]);
board[row-1][col].reveal();
numSafeSpots--;
}
if (!board[row+1][col].isRevealed() && !board[row+1][col].isWrapper()) {
q.add(board[row+1][col]);
board[row+1][col].reveal();
numSafeSpots--;
}
if (!board[row][col-1].isRevealed() && !board[row][col-1].isWrapper()) {
q.add(board[row][col-1]);
board[row][col-1].reveal();
numSafeSpots--;
}
if (!board[row][col+1].isRevealed() && !board[row][col+1].isWrapper()) {
q.add(board[row][col+1]);
board[row][col+1].reveal();
numSafeSpots--;
}
if (!board[row-1][col-1].isRevealed() && !board[row-1][col-1].isWrapper()) {
q.add(board[row-1][col-1]);
board[row-1][col-1].reveal();
numSafeSpots--;
}
if (!board[row+1][col-1].isRevealed() && !board[row+1][col-1].isWrapper()) {
q.add(board[row+1][col-1]);
board[row+1][col-1].reveal();
numSafeSpots--;
}
if (!board[row-1][col+1].isRevealed() && !board[row-1][col+1].isWrapper()) {
q.add(board[row-1][col+1]);
board[row-1][col+1].reveal();
numSafeSpots--;
}
if (!board[row+1][col+1].isRevealed() && !board[row+1][col+1].isWrapper()) {
q.add(board[row+1][col+1]);
board[row+1][col+1].reveal();
numSafeSpots--;
}
}
}
And for a shorthand version which is slightly less efficient (since the current cell is being checked):
Code: Select all
public void floodFill(int row, int col) {
Queue<MButton> q = new LinkedList<MButton>();
if (!board[row][col].isEmpty())
return;
q.add(board[row][col]);
MButton mb;
while(!q.isEmpty()) {
mb = q.remove();
if (!mb.isRevealed()) {
mb.reveal();
numSafeSpots--;
if (numSafeSpots == 0)
win();
}
if (!mb.isEmpty())
continue;
row = mb.rowPosition();
col = mb.colPosition();
for (int i=row-1; i < row + 2; i++)
for (int j=col-1; j < col + 2; j++) {
if (!board[i][j].isRevealed() && !board[i][j].isWrapper()) {
q.add(board[i][j]);
board[i][j].reveal();
numSafeSpots--;
}
}
}
}