当前位置:首页 > 后端开发 > 正文

java扫雷游戏编程怎么自定义雷区

Java扫雷游戏中,自定义雷区可通过创建二维数组表示格子,随机

Java 中实现扫雷游戏并自定义雷区,需要从多个方面入手,包括游戏界面的设计、雷区数据的生成与存储、以及雷区相关的逻辑处理等,以下是一个详细的实现方案:

游戏界面设计

扫雷游戏通常有一个二维的网格来表示雷区,每个网格可以是一个按钮或者一个可绘制的区域,用于显示数字、雷或者空白等信息,可以使用 Java 的 Swing 或 JavaFX 库来创建图形用户界面(GUI)。

java扫雷游戏编程怎么自定义雷区  第1张

使用 Swing 创建基本界面

import javax.swing.;
import java.awt.;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Minesweeper extends JFrame {
    private JPanel panel;
    private int rows = 10; // 默认行数
    private int cols = 10; // 默认列数
    private JButton[][] buttons;
    public Minesweeper() {
        setTitle("扫雷游戏");
        setSize(400, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        panel = new JPanel(new GridLayout(rows, cols));
        buttons = new JButton[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                buttons[i][j] = new JButton();
                buttons[i][j].addActionListener(new ButtonClickListener(i, j));
                panel.add(buttons[i][j]);
            }
        }
        add(panel);
        setVisible(true);
    }
    private class ButtonClickListener implements ActionListener {
        int row;
        int col;
        public ButtonClickListener(int row, int col) {
            this.row = row;
            this.col = col;
        }
        @Override
        public void actionPerformed(ActionEvent e) {
            // 处理按钮点击事件,如揭示雷区、判断胜负等
            // 这里可以根据自定义雷区的数据来进行相应的处理
        }
    }
    public static void main(String[] args) {
        new Minesweeper();
    }
}

雷区数据生成与存储

为了自定义雷区,我们需要一个数据结构来存储雷区的信息,例如哪些格子是雷,每个格子周围的雷数等,可以使用一个二维数组来表示雷区,其中每个元素可以是布尔值(表示是否是雷)或者整数(表示周围雷的数量)。

定义雷区数据结构

boolean[][] mines; // 存储雷的位置,true 表示有雷,false 表示无雷
int[][] numbers;   // 存储每个格子周围的雷数

初始化雷区数据

在游戏开始时,根据自定义的参数(如雷区大小、雷的数量等)来初始化 minesnumbers 数组。

public void initializeMinefield(int rows, int cols, int numMines) {
    this.rows = rows;
    this.cols = cols;
    mines = new boolean[rows][cols];
    numbers = new int[rows][cols];
    // 随机放置雷
    Random random = new Random();
    int minesPlaced = 0;
    while (minesPlaced < numMines) {
        int r = random.nextInt(rows);
        int c = random.nextInt(cols);
        if (!mines[r][c]) {
            mines[r][c] = true;
            minesPlaced++;
        }
    }
    // 计算每个格子周围的雷数
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            if (!mines[i][j]) {
                int count = 0;
                for (int dr = -1; dr <= 1; dr++) {
                    for (int dc = -1; dc <= 1; dc++) {
                        int ni = i + dr;
                        int nj = j + dc;
                        if (ni >= 0 && ni < rows && nj >= 0 && nj < cols && mines[ni][nj]) {
                            count++;
                        }
                    }
                }
                numbers[i][j] = count;
            }
        }
    }
}

自定义雷区参数

为了让用户能够自定义雷区,可以在游戏界面上添加一些输入控件,如文本框或下拉菜单,让用户输入雷区的行数、列数和雷的数量等参数。

添加自定义参数输入控件

private JTextField rowsField;
private JTextField colsField;
private JTextField minesField;
private JButton customizeButton;
public Minesweeper() {
    // ... 之前的代码
    JPanel configPanel = new JPanel();
    configPanel.add(new JLabel("行数:"));
    rowsField = new JTextField("10", 3);
    configPanel.add(rowsField);
    configPanel.add(new JLabel("列数:"));
    colsField = new JTextField("10", 3);
    configPanel.add(colsField);
    configPanel.add(new JLabel("雷数:"));
    minesField = new JTextField("15", 3);
    configPanel.add(minesField);
    customizeButton = new JButton("自定义雷区");
    customizeButton.addActionListener(new CustomizeButtonListener());
    configPanel.add(customizeButton);
    add(configPanel, BorderLayout.NORTH);
}
private class CustomizeButtonListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        try {
            int rows = Integer.parseInt(rowsField.getText());
            int cols = Integer.parseInt(colsField.getText());
            int mines = Integer.parseInt(minesField.getText());
            if (rows > 0 && cols > 0 && mines >= 0 && mines <= rows  cols) {
                initializeMinefield(rows, cols, mines);
                // 更新界面上的按钮数量以匹配新的雷区大小
                panel.removeAll();
                buttons = new JButton[rows][cols];
                for (int i = 0; i < rows; i++) {
                    for (int j = 0; j < cols; j++) {
                        buttons[i][j] = new JButton();
                        buttons[i][j].addActionListener(new ButtonClickListener(i, j));
                        panel.add(buttons[i][j]);
                    }
                }
                panel.revalidate();
                panel.repaint();
            } else {
                JOptionPane.showMessageDialog(null, "请输入有效的参数!");
            }
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(null, "请输入数字!");
        }
    }
}

处理按钮点击事件

当用户点击一个按钮时,需要根据雷区数据来判断该位置是否是雷,或者是周围有多少雷,并在按钮上显示相应的信息,还需要处理游戏的胜负逻辑。

揭示雷区信息

@Override
public void actionPerformed(ActionEvent e) {
    int row = this.row;
    int col = this.col;
    if (!mines[row][col]) {
        buttons[row][col].setText(String.valueOf(numbers[row][col]));
        buttons[row][col].setEnabled(false);
        // 递归揭示周围没有雷且周围雷数为 0 的格子
        revealEmptyCells(row, col);
    } else {
        // 点击到雷,游戏结束
        buttons[row][col].setText("雷");
        revealAllMines();
        JOptionPane.showMessageDialog(null, "你输了!");
    }
}
private void revealEmptyCells(int row, int col) {
    if (row < 0 || row >= rows || col < 0 || col >= cols || !buttons[row][col].isEnabled()) {
        return;
    }
    if (numbers[row][col] == 0) {
        buttons[row][col].setText("");
        buttons[row][col].setEnabled(false);
        for (int dr = -1; dr <= 1; dr++) {
            for (int dc = -1; dc <= 1; dc++) {
                revealEmptyCells(row + dr, col + dc);
            }
        }
    } else if (numbers[row][col] > 0) {
        buttons[row][col].setText(String.valueOf(numbers[row][col]));
        buttons[row][col].setEnabled(false);
    }
}

揭示所有雷(用于游戏结束显示)

private void revealAllMines() {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            if (mines[i][j]) {
                buttons[i][j].setText("雷");
            } else if (buttons[i][j].isEnabled()) {
                buttons[i][j].setText(String.valueOf(numbers[i][j]));
                buttons[i][j].setEnabled(false);
            }
        }
    }
}

判断游戏胜利

当用户成功揭示所有非雷的格子时,游戏胜利,可以通过一个计数器来记录已经揭示的非雷格子数量,当这个数量等于总非雷格子数量时,判断为胜利。

private int revealedCells = 0;
private int totalNonMineCells = rows  cols numMines;
private void checkWin() {
    if (revealedCells == totalNonMineCells) {
        JOptionPane.showMessageDialog(null, "你赢了!");
        // 可以在这里添加重置游戏或其他操作的代码
    }
}

actionPerformed 方法中,每次成功揭示一个非雷格子后,增加 revealedCells 计数器,并调用 checkWin 方法检查是否胜利,如果是点击到雷导致游戏结束,则不需要增加计数器。

@Override
public void actionPerformed(ActionEvent e) {
    int row = this.row;
    int col = this.col;
    if (!mines[row][col]) {
        revealedCells++;
        buttons[row][col].setText(String.valueOf(numbers[row][col]));
        buttons[row][col].setEnabled(false);
        if (numbers[row][col] == 0) {
            revealEmptyCells(row, col);
        }
        checkWin();
    } else {
        buttons[row][col].setText("雷");
        revealAllMines();
        JOptionPane.showMessageDialog(null, "你输了!");
    }
}
```这样,就实现了一个基本的可以自定义雷区的 Java 扫雷游戏,你可以进一步优化界面、添加更多功能,如计时、排行榜等,提升游戏的趣味性和完整性,以下是一个简单的相关问答FAQs:问题1:如何改变雷区的大小?答:在游戏界面的输入框中分别输入想要的行数、列数和雷数,然后点击“自定义雷区”按钮,程序会根据输入的参数重新初始化雷区并更新界面上的按钮布局。问题2:游戏中的数字代表什么意思?答:游戏中的数字表示该格子周围8个相邻格子中雷的数量,数字“3”表示该格子周围有3个雷,通过点击格子来揭示这些数字,从而帮助玩家判断雷的位置,避免踩雷,如果点击到雷,游戏结束;

0