以下是用Java开发一个扫雷游戏的基本步骤:
-
创建一个窗口和画布,用来显示游戏界面。
-
创建一个游戏逻辑类,包含一些基本的操作,如生成地雷、计算周围地雷数量、打开方格等。
-
在画布上绘制游戏界面,包括格子、数字、地雷等。
-
给格子添加鼠标事件,实现左键点击打开方格、右键点击插上旗子等操作。
-
实现游戏的胜利和失败判定,包括所有非地雷方格都被打开、点中地雷等。
效果如下:
以下是一个简单的代码示例:
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class MineSweeper extends JPanel {
private int[][] grid;
private boolean[][] reveal;
private int numMines;
private int gridSize;
private final int BLOCK_SIZE = 30;
private final int MARGIN = 20;
public MineSweeper(int gridSize, int numMines) {
this.gridSize = gridSize;
this.numMines = numMines;
grid = new int[gridSize][gridSize];
reveal = new boolean[gridSize][gridSize];
setPreferredSize(new Dimension(gridSize * BLOCK_SIZE + MARGIN * 2, gridSize * BLOCK_SIZE + MARGIN * 2));
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
handleClick(e.getX(), e.getY(), e.getButton());
}
});
generateGrid();
}
private void generateGrid() {
Random rnd = new Random();
int count = 0;
while (count < numMines) {
int x = rnd.nextInt(gridSize);
int y = rnd.nextInt(gridSize);
if (grid[x][y] != -1) {
grid[x][y] = -1;
count++;
}
}
for (int i = 0; i < gridSize; i++) {
for (int j = 0; j < gridSize; j++) {
if (grid[i][j] != -1) {
int countMines = 0;
for (int x = Math.max(i - 1, 0); x <= Math.min(i + 1, gridSize - 1); x++) {
for (int y = Math.max(j - 1, 0); y <= Math.min(j + 1, gridSize - 1); y++) {
if (grid[x][y] == -1) {
countMines++;
}
}
}
grid[i][j] = countMines;
}
}
}
}
private void handleClick(int x, int y, int button) {
if (x < MARGIN || x >= MARGIN + gridSize * BLOCK_SIZE || y < MARGIN || y >= MARGIN + gridSize * BLOCK_SIZE) {
return;
}
int i = (x - MARGIN) / BLOCK_SIZE;
int j = (y - MARGIN) / BLOCK_SIZE;
if (button == MouseEvent.BUTTON1) {
if (reveal[i][j]) {
return;
}
reveal[i][j] = true;
if (grid[i][j] == -1) {
JOptionPane.showMessageDialog(this, "You click a mine! Try again!");
generateGrid();
} else if (grid[i][j] == 0) {
for (int x1 = Math.max(i - 1, 0); x1 <= Math.min(i + 1, gridSize - 1); x1++) {
for (int y1 = Math.max(j - 1, 0); y1 <= Math.min(j + 1, gridSize - 1); y1++) {
if (!reveal[x1][y1]) {
handleClick(MARGIN + x1 * BLOCK_SIZE + BLOCK_SIZE / 2, MARGIN + y1 * BLOCK_SIZE + BLOCK_SIZE / 2, MouseEvent.BUTTON1);
}
}
}
}
} else if (button == MouseEvent.BUTTON3) {
reveal[i][j] = !reveal[i][j];
}
repaint();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(MARGIN, MARGIN, gridSize * BLOCK_SIZE, gridSize * BLOCK_SIZE);
for (int i = 0; i < gridSize; i++) {
for (int j = 0; j < gridSize; j++) {
if (reveal[i][j]) {
g.setColor(Color.WHITE);
g.fillRect(MARGIN + i * BLOCK_SIZE, MARGIN + j * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
if (grid[i][j] == -1) {
g.setColor(Color.RED);
g.fillRect(MARGIN + i * BLOCK_SIZE, MARGIN + j * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
} else if (grid[i][j] > 0) {
g.setColor(Color.BLUE);
g.setFont(new Font("Arial", Font.BOLD, BLOCK_SIZE / 2));
g.drawString("" + grid[i][j], MARGIN + i * BLOCK_SIZE + BLOCK_SIZE / 4, MARGIN + j * BLOCK_SIZE + BLOCK_SIZE / 2);
}
} else {
g.setColor(Color.GRAY);
g.fillRect(MARGIN + i * BLOCK_SIZE, MARGIN + j * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
if (reveal[i][j]) {
g.setColor(Color.WHITE);
g.fillRect(MARGIN + i * BLOCK_SIZE, MARGIN + j * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
} else {
g.setColor(Color.BLACK);
g.drawRect(MARGIN + i * BLOCK_SIZE, MARGIN + j * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE);
}
}
}
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Mine Sweeper");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.add(new MineSweeper(10, 10));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}