I am fairly new to Java and I have been working on a Minesweeper game. I am trying to get the adjacent cells to be revealed recursively when an empty cell is clicked. I do this by calling showCell() shown below:
Cells array declaration and population:
private final Cell[][] cells; public void newGame() { numMinesLeft = NUM_MINES; numCellsLeft = NUM_ROWS * NUM_COLS; hasHitMine = false; Cell[] newCells = new Cell[NUM_ROWS * NUM_COLS]; int k = 0; // index in newCells // create the cells with the mines while (k < NUM_MINES && k < newCells.length) { newCells[k] = new Cell(MINE); k++; } // create the cells without the mines while (k < newCells.length) { newCells[k] = new Cell(); k++; } // uniformly mix newCells for (k = newCells.length; k > 1;) { int r = generator.nextInt(k); k--; // interchange newCells[r] and newCells[k] Cell temp = newCells[k]; newCells[k] = newCells[r]; newCells[r] = temp; } k = 0; // place cells into the cells array for (int i = 0; i < NUM_ROWS; ++i) { for (int j = 0; j < NUM_COLS; ++j) { cells[i][j] = newCells[k]; k++; } } for(int i = 0; i<NUM_ROWS; i++) { for (int j = 0; j<NUM_COLS; j++) { int numOfBorderMines = 0; if (cells[i][j].value != MINE) { if(isInTheGrid(i-1, j) == true) { if (cells[i-1][j].value == MINE ) { numOfBorderMines++; } } if(isInTheGrid(i+1, j) == true) { if (cells[i+1][j].value == MINE ) { numOfBorderMines++; } } if(isInTheGrid(i, j - 1) == true) { if (cells[i][j - 1].value == MINE ) { numOfBorderMines++; } } if(isInTheGrid(i, j + 1) == true) { if (cells[i][j + 1].value == MINE ) { numOfBorderMines++; } } if(isInTheGrid(i - 1, j + 1) == true) { if (cells[i - 1][j + 1].value == MINE ) { numOfBorderMines++; } } if(isInTheGrid(i + 1, j - 1) == true) { if (cells[i + 1][j - 1].value == MINE ) { numOfBorderMines++; } } if(isInTheGrid(i + 1, j + 1) == true) { if (cells[i + 1][j + 1].value == MINE ) { numOfBorderMines++; } } if(isInTheGrid(i - 1, j - 1) == true) { if (cells[i - 1][j - 1].value == MINE ) { numOfBorderMines++; } } cells[i][j].value = numOfBorderMines; } } } }
toggleFlag()
public void toggleFlag(int row, int col) { if (isCellShowing(row, col) || isOver()) return; if (isCellFlagged(row, col)) { // unflag cell cells[row][col].hasFlag = false; numMinesLeft++; numCellsLeft++; } else if (numMinesLeft > 0) { // flag cell cells[row][col].hasFlag = true; numMinesLeft--; numCellsLeft--; } ui.updateCell(row, col); }
showCell()
public void showCell(int row, int col) { // checks is cell has been flagged or if the game is over, otherwise it reveals the cell if(isCellFlagged(row, col) == true || isOver()) { return; } else { cells[row][col].isShowing = true; ui.updateCell(row, col); } // checks if cell has a mine and triggers hasHitMine otherwise subtracts 1 from class variable numCellsLeft if (cells[row][col].value == MINE) { hasHitMine = true; } else { numCellsLeft--; } // if there are no mines adjacent, recursively reveal the adjacent cells if(cells[row][col].value == 0) { showCell(row + 1, col); showCell(row - 1, col); showCell(row, col + 1); showCell(row, col -1); showCell(row + 1, col - 1); showCell(row + 1, col + 1); showCell(row - 1, col - 1); showCell(row - 1, col + 1); } }
The problem I am having is when I hit this portion of the code and click an empty cell, it reveals all cells adjacent continuously down a column or a row in one direction. I can’t get my implementation of recursion right, perhaps I am approaching it wrong. My idea was to reveal each adjacent cell according to the grid position.
Advertisement
Answer
I solved my problem by implementing Tail Recursion. Here is my updated showCell() method and tail recursion method:
public void showCell(int row, int col) { // checks is cell has been flagged or if the game is over, otherwise it reveals the cell if(isCellFlagged(row, col) == true || isOver()) { return; } else { cells[row][col].isShowing = true; ui.updateCell(row, col); } // checks if cell has a mine and triggers hasHitMine otherwise subtracts 1 from class variable numCellsLeft if (cells[row][col].value == MINE) { hasHitMine = true; } else { numCellsLeft--; } // if there are no mines adjacent, recursively reveal the adjacent cells if(cells[row][col].value == 0) { if(isInTheGrid(row - 1, col) == true) { showCell(row - 1, col, cells[row - 1][col].isShowing); } if(isInTheGrid(row + 1, col) == true) { showCell(row + 1, col, cells[row + 1][col].isShowing); } if(isInTheGrid(row, col - 1) == true) { showCell(row, col - 1, cells[row][col - 1].isShowing); } if(isInTheGrid(row, col + 1) == true) { showCell(row, col + 1, cells[row][col + 1].isShowing); } if(isInTheGrid(row + 1, col - 1) == true) { showCell(row + 1, col - 1, cells[row + 1][col - 1].isShowing); } if(isInTheGrid(row - 1, col + 1) == true) { showCell(row - 1, col + 1, cells[row - 1][col + 1].isShowing); } if(isInTheGrid(row + 1, col + 1) == true) { showCell(row + 1, col + 1, cells[row + 1][col + 1].isShowing); } if(isInTheGrid(row - 1, col - 1) == true) { showCell(row - 1, col - 1, cells[row - 1][col - 1].isShowing); } } else { return; } } public boolean isInTheGrid(int x, int y) { if (x < 0 || y < 0) return false; if(x >= NUM_ROWS || y >= NUM_COLS) return false; return true; } public void showCell(int row, int col, boolean isShown) { if (isShown != true) { cells[row][col].isShowing = true; ui.updateCell(row, col); } else { return; } }