递归显示扫雷器中相邻的空白地雷

Recursion Showing Adjacent Blank Mines in Minesweeper

我是 Java 的新手,我一直在开发扫雷游戏。我试图在单击空单元格时递归显示相邻的单元格。我通过调用如下所示的 showCell() 来做到这一点:

单元格数组声明和填充:

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

    }

我遇到的问题是,当我点击这部分代码并单击一个空单元格时,它会显示沿一个方向连续向下一列或一行相邻的所有单元格。我无法正确实现递归,也许我做错了。我的想法是根据网格位置显示每个相邻的单元格。

当您为周围的单元格调用 show cell 时,您要确保不会重新显示调用它的单元格,或者递归堆栈中先前调用显示的过去的单元格。

如果我没有正确理解你的问题,我相信你指的是扫雷中的案例,如果你点击一个空单元格,它会显示相邻的空单元格。

我通过实现尾递归解决了我的问题。这是我更新的 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)
        {
            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;
        }
    }