Recursion Showing Adjacent Blank Mines in Minesweeper



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.

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;
        }
    }


Source: stackoverflow