|
|
|
@ -1,289 +1,308 @@
|
|
|
|
|
package com.first;
|
|
|
|
|
|
|
|
|
|
import java.awt.Color;
|
|
|
|
|
import java.awt.Dimension;
|
|
|
|
|
import java.awt.Image;
|
|
|
|
|
import java.awt.Insets;
|
|
|
|
|
import java.awt.Toolkit;
|
|
|
|
|
import java.awt.event.ActionEvent;
|
|
|
|
|
import java.awt.event.ActionListener;
|
|
|
|
|
import java.awt.event.MouseAdapter;
|
|
|
|
|
import java.awt.event.MouseEvent;
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
|
|
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
|
import javax.swing.BorderFactory;
|
|
|
|
|
import javax.swing.ImageIcon;
|
|
|
|
|
import javax.swing.JButton;
|
|
|
|
|
import javax.swing.JFrame;
|
|
|
|
|
import javax.swing.JLabel;
|
|
|
|
|
import javax.swing.JOptionPane;
|
|
|
|
|
import javax.swing.JPanel;
|
|
|
|
|
import javax.swing.SwingConstants;
|
|
|
|
|
import javax.swing.UIManager;
|
|
|
|
|
|
|
|
|
|
public class MineSweeper {
|
|
|
|
|
static private GamePanel gPanel;/* 雷区 */
|
|
|
|
|
static private int midtime = 3600, mineNum = 0;/* 倒计时时间以及可用旗子数量 */
|
|
|
|
|
static private JLabel label1, label2;
|
|
|
|
|
static CountDown cd;
|
|
|
|
|
/**
|
|
|
|
|
* 构造函数 用于初始化
|
|
|
|
|
*/
|
|
|
|
|
public MineSweeper() {
|
|
|
|
|
JFrame jf = new JFrame("扫雷小游戏");
|
|
|
|
|
jf.setDefaultCloseOperation(3);// EXIT_ON_CLOSE,直接关闭应用程序,System.exit(0)。一个main函数对应一整个程序。
|
|
|
|
|
jf.setLayout(null);// 未设置Layout时,java默认为flowLayout布局的,设置为null即为清空布局管理器,之后添加组件,常常是设置组件左上角坐标相对于容器左上角(0,0)的x,y值来确定组件的位置
|
|
|
|
|
jf.setBounds(600, 200, 700, 800);// 设置窗口的大小和位置
|
|
|
|
|
label1 = new JLabel("剩余时间:" + (midtime / 60 / 60 % 60) + ":" + (midtime / 60 % 60) + ":" + (midtime % 60));
|
|
|
|
|
label1.setBounds(10, 20, 120, 20);
|
|
|
|
|
jf.add(label1);
|
|
|
|
|
label2 = new JLabel("剩余旗子:" + mineNum);
|
|
|
|
|
label2.setBounds(400, 20, 240, 20);// 设置label2的位置以及大小
|
|
|
|
|
jf.add(label2);
|
|
|
|
|
JButton resetButt = new JButton("重置");// 创建重置按钮
|
|
|
|
|
resetButt.setMargin(new Insets(0, 0, 0, 0));// 设置边框
|
|
|
|
|
resetButt.setBounds(230, 15, 60, 30);// 设置按钮在窗口中的位置和大小
|
|
|
|
|
resetButt.addActionListener(new ActionListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void actionPerformed(ActionEvent e) {
|
|
|
|
|
// TODO Auto-generated method stub
|
|
|
|
|
jf.dispose();/* 销毁窗口 */
|
|
|
|
|
new MineSweeper();
|
|
|
|
|
midtime = 3600;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
jf.add(resetButt);// 把按钮添加到窗口中
|
|
|
|
|
gPanel = new GamePanel(20, 20);// 设置按钮数量为20行*20列
|
|
|
|
|
gPanel.setBounds(40, 100, 600, 600);// 设置雷区面板的位置以及大小
|
|
|
|
|
jf.add(gPanel);// 雷区面板添加到窗口中
|
|
|
|
|
jf.setVisible(true);// 设置窗口可见
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static class CountDown extends Thread {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
super.run();
|
|
|
|
|
while (midtime > 0) {
|
|
|
|
|
try {
|
|
|
|
|
--midtime;
|
|
|
|
|
label1.setText(
|
|
|
|
|
"剩余时间:" + (midtime / 60 / 60 % 60) + ":" + (midtime / 60 % 60) + ":" + (midtime % 60));
|
|
|
|
|
sleep(1000);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (midtime == 0) {
|
|
|
|
|
JOptionPane.showMessageDialog(null, "时间已到", "游戏结束", JOptionPane.PLAIN_MESSAGE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {// 程序的入口
|
|
|
|
|
new MineSweeper();// 进入构造函数
|
|
|
|
|
cd = new CountDown();// 创建计时器
|
|
|
|
|
cd.start();/* 启动计时器 */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void setMineNum(int minesCount2) {
|
|
|
|
|
// TODO Auto-generated method stub
|
|
|
|
|
mineNum = minesCount2;
|
|
|
|
|
label2.setText("剩余旗子:" + mineNum);
|
|
|
|
|
}
|
|
|
|
|
static private GamePanel gPanel;/* 雷区 */
|
|
|
|
|
static private int midtime = 3600, mineNum = 0;/* 倒计时时间以及可用旗子数量 */
|
|
|
|
|
static private JLabel label1, label2;
|
|
|
|
|
static CountDown cd;
|
|
|
|
|
|
|
|
|
|
public MineSweeper() {
|
|
|
|
|
JFrame jf = new JFrame("扫雷小游戏");
|
|
|
|
|
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
|
|
|
jf.setLayout(null);
|
|
|
|
|
jf.setBounds(600, 200, 700, 800);
|
|
|
|
|
|
|
|
|
|
label1 = new JLabel("剩余时间:" + formatTime(midtime));
|
|
|
|
|
label1.setBounds(10, 20, 120, 20);
|
|
|
|
|
jf.add(label1);
|
|
|
|
|
|
|
|
|
|
label2 = new JLabel("剩余旗子:" + mineNum);
|
|
|
|
|
label2.setBounds(400, 20, 240, 20);
|
|
|
|
|
jf.add(label2);
|
|
|
|
|
|
|
|
|
|
JButton resetButt = new JButton("重置");
|
|
|
|
|
resetButt.setMargin(new Insets(0, 0, 0, 0));
|
|
|
|
|
resetButt.setBounds(230, 15, 60, 30);
|
|
|
|
|
resetButt.addActionListener(e -> {
|
|
|
|
|
jf.dispose();
|
|
|
|
|
new MineSweeper();
|
|
|
|
|
midtime = 3600;
|
|
|
|
|
});
|
|
|
|
|
jf.add(resetButt);
|
|
|
|
|
|
|
|
|
|
gPanel = new GamePanel(20, 20);
|
|
|
|
|
gPanel.setBounds(40, 100, 600, 600);
|
|
|
|
|
jf.add(gPanel);
|
|
|
|
|
|
|
|
|
|
jf.setVisible(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static class CountDown extends Thread {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
super.run();
|
|
|
|
|
while (midtime > 0) {
|
|
|
|
|
try {
|
|
|
|
|
--midtime;
|
|
|
|
|
label1.setText("剩余时间:" + formatTime(midtime));
|
|
|
|
|
sleep(1000);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (midtime == 0) {
|
|
|
|
|
JOptionPane.showMessageDialog(null, "时间已到", "游戏结束", JOptionPane.PLAIN_MESSAGE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static String formatTime(int seconds) {
|
|
|
|
|
int hrs = seconds / 3600;
|
|
|
|
|
int mins = (seconds % 3600) / 60;
|
|
|
|
|
int secs = seconds % 60;
|
|
|
|
|
return String.format("%02d:%02d:%02d", hrs, mins, secs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
new MineSweeper();
|
|
|
|
|
cd = new CountDown();
|
|
|
|
|
cd.start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void setMineNum(int minesCount2) {
|
|
|
|
|
mineNum = minesCount2;
|
|
|
|
|
label2.setText("剩余旗子:" + mineNum);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class GamePanel extends JPanel {
|
|
|
|
|
private int rows, cols, minesCount;// 创建行数、列数变量,地雷的数量
|
|
|
|
|
private final int BLOCKWIDTH = 30;// 规定每个按钮的宽度
|
|
|
|
|
private final int BLOCKHEIGHT = 30;// 规定每个按钮的高度
|
|
|
|
|
private Buts[][] buts;// 雷区按钮
|
|
|
|
|
private JLabel[][] jlabel;// 每个按钮下对应标签
|
|
|
|
|
private boolean[][] state;// true:有雷;false:没有雷
|
|
|
|
|
private int[][] click;// 0:未点击,1:已点击,2:未点击但周围有雷,3:插旗
|
|
|
|
|
public GamePanel(int row, int col) {
|
|
|
|
|
rows = row;// 行数
|
|
|
|
|
cols = col;// 列数
|
|
|
|
|
minesCount = rows * cols / 10;// 地雷的数量
|
|
|
|
|
MineSweeper.setMineNum(minesCount);
|
|
|
|
|
buts = new Buts[rows][cols];// 创建雷区按钮
|
|
|
|
|
jlabel = new JLabel[rows][cols];// 创建标签
|
|
|
|
|
state = new boolean[rows][cols];// true:有雷;false:没有雷
|
|
|
|
|
click = new int[rows][cols];// 0:未点击,1:已点击,2:未点击但周围有雷,3:插旗
|
|
|
|
|
setLayout(null);// 设置为null即为清空布局管理器,之后添加组件,常常是设置组件左上角坐标相对于容器左上角(0,0)的x,y值来确定组件的位置
|
|
|
|
|
initButtons();// 初始化按钮,设置每个按钮的基本参数
|
|
|
|
|
initLable();// 初始化标签方格,设置每个标签的基本参数
|
|
|
|
|
buryMines();// 埋雷,随机生成地雷
|
|
|
|
|
writerNumber();// 计算每个方格周围8个方格中有几个地雷
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 用于统计每个方格周围有多少地雷 */
|
|
|
|
|
private void writerNumber() {
|
|
|
|
|
for (int i = 0; i < rows; i++) {
|
|
|
|
|
for (int j = 0; j < cols; j++) {
|
|
|
|
|
if (!state[i][j]) {// 没有雷的地方才探测周围的情况
|
|
|
|
|
int numbers = 0;// 用于记录每个方格四周有多少地雷
|
|
|
|
|
for (int r = -1; r < 2; r++) {// 探测每个方格行坐标-1,0,+1后的情况
|
|
|
|
|
for (int c = -1; c < 2; c++) {// 探测每个方格列坐标-1,0,+1后的情况
|
|
|
|
|
if ((i + r > -1) && (i + r < cols) && (j + c > -1) && (j + c < rows)) {// 判断有没有超过数组的边界
|
|
|
|
|
if (state[i + r][j + c] == true) {// 探测的位置上有地雷则numbers加1
|
|
|
|
|
numbers++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (numbers > 0) {
|
|
|
|
|
click[i][j] = 2;// 设置为:未点击但周围有雷
|
|
|
|
|
}
|
|
|
|
|
jlabel[i][j].setText(String.valueOf(numbers));// 给每个单元赋值,周围8个方格中有几个地雷
|
|
|
|
|
// buts[i][j].setText(String.valueOf(numbers));// 调试代码用
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void initButtons() {
|
|
|
|
|
for (int i = 0; i < rows; i++) {
|
|
|
|
|
for (int j = 0; j < cols; j++) {
|
|
|
|
|
Buts but = new Buts();
|
|
|
|
|
but.i = i;// 给按钮的行信息赋值
|
|
|
|
|
but.j = j;// 给按钮的列信息赋值
|
|
|
|
|
but.setBounds(BLOCKWIDTH * j, BLOCKHEIGHT * i, BLOCKWIDTH, BLOCKHEIGHT);// 设置每一个按钮的位置和大小
|
|
|
|
|
but.setMargin(new Insets(0, 0, 0, 0));// 设置按钮边框
|
|
|
|
|
/* 给按钮添加鼠标监听器,检测是否点击 */
|
|
|
|
|
but.addMouseListener(new MouseAdapter() {
|
|
|
|
|
@Override
|
|
|
|
|
public void mouseClicked(MouseEvent e) {
|
|
|
|
|
/* 左击 */
|
|
|
|
|
if (e.getButton() == MouseEvent.BUTTON1) {
|
|
|
|
|
// but.setVisible(false);//调试代码用
|
|
|
|
|
// jlabel[but.i][but.j].setVisible(true);//调试代码用
|
|
|
|
|
openButtons(but);
|
|
|
|
|
}
|
|
|
|
|
/* 右击 */
|
|
|
|
|
if (e.getButton() == MouseEvent.BUTTON3) {
|
|
|
|
|
// but.setText("旗");// 调试代码用
|
|
|
|
|
placeFlag(but);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
buts[i][j] = but;// 赋值给公共变量,方便调用
|
|
|
|
|
this.add(buts[i][j]);// 添加到面板中jpanel
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void placeFlag(Buts but) {
|
|
|
|
|
if (click[but.i][but.j] != 3) {
|
|
|
|
|
buts[but.i][but.j].setText("旗");
|
|
|
|
|
// System.out.println("click[but.i][but.j] =" + click[but.i][but.j]);// 调试代码用
|
|
|
|
|
click[but.i][but.j] = 3;// 0:未点击,1:已点击,2:未点击但周围有雷,3:插旗
|
|
|
|
|
minesCount--;
|
|
|
|
|
MineSweeper.setMineNum(minesCount);
|
|
|
|
|
} else {
|
|
|
|
|
buts[but.i][but.j].setText("");
|
|
|
|
|
if (!state[but.i][but.j]) {
|
|
|
|
|
if (Integer.valueOf(jlabel[but.i][but.j].getText()) > 0) {
|
|
|
|
|
click[but.i][but.j] = 2;// 周围有地雷
|
|
|
|
|
// System.out.println("click[but.i][but.j] =" + click[but.i][but.j]);// 调试代码用
|
|
|
|
|
} else {
|
|
|
|
|
click[but.i][but.j] = 0;// 未点击
|
|
|
|
|
// System.out.println("click[but.i][but.j] =" + click[but.i][but.j]);// 调试代码用
|
|
|
|
|
}
|
|
|
|
|
minesCount++;
|
|
|
|
|
MineSweeper.setMineNum(minesCount);
|
|
|
|
|
} else {
|
|
|
|
|
click[but.i][but.j] = 0;// 未点击
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if (minesCount == 0) {// 当旗子用完后,判断是否全部标记正确
|
|
|
|
|
boolean flag = true;
|
|
|
|
|
for (int i = 0; i < rows; i++) {
|
|
|
|
|
for (int j = 0; j < cols; j++) {
|
|
|
|
|
if ((click[i][j] != 3) && (state[i][j])) {// 对所有没有插旗的方格进行判断,如果没有插旗,但是state的状态又未true,则令flag未false
|
|
|
|
|
flag = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (flag) {
|
|
|
|
|
MineSweeper.cd.stop();// 停止计时
|
|
|
|
|
JOptionPane.showMessageDialog(null, "您成功了", "游戏结束", JOptionPane.PLAIN_MESSAGE);
|
|
|
|
|
} else {
|
|
|
|
|
MineSweeper.cd.stop();// 停止计时
|
|
|
|
|
JOptionPane.showMessageDialog(null, "旗子已经用完", "游戏失败", JOptionPane.PLAIN_MESSAGE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void openButtons(Buts but) {
|
|
|
|
|
int i = but.i;
|
|
|
|
|
int j = but.j;
|
|
|
|
|
if (state[i][j] && (click[i][j] != 3)) {
|
|
|
|
|
openAllCell();
|
|
|
|
|
MineSweeper.cd.stop();
|
|
|
|
|
JOptionPane.showMessageDialog(null, "您踩到地雷了", "游戏结束", JOptionPane.PLAIN_MESSAGE);
|
|
|
|
|
}
|
|
|
|
|
if (click[i][j] == 2) {
|
|
|
|
|
buts[i][j].setVisible(false);
|
|
|
|
|
jlabel[i][j].setVisible(true);
|
|
|
|
|
}
|
|
|
|
|
if ((click[i][j] == 0) || (click[i][j] == 1)) {// 0的周围是要判断的,1的周围也有可能所以也要判断
|
|
|
|
|
for (int r = -1; r < 2; r++) {
|
|
|
|
|
for (int c = -1; c < 2; c++) {
|
|
|
|
|
if ((i + r > -1) && (i + r < cols) && (j + c > -1) && (j + c < rows) && (!state[i + r][j + c])) {// 判断有没有超过数组的边界
|
|
|
|
|
if (click[i + r][j + c] == 0) {// 0:未点击,1:已点击,2:未点击但周围有雷,3:插旗
|
|
|
|
|
buts[i + r][j + c].setVisible(false);
|
|
|
|
|
jlabel[i + r][j + c].setVisible(true);
|
|
|
|
|
click[i + r][j + c] = 1;
|
|
|
|
|
openButtons(buts[i + r][j + c]);
|
|
|
|
|
}
|
|
|
|
|
if (click[i + r][j + c] == 2) {
|
|
|
|
|
buts[i + r][j + c].setVisible(false);
|
|
|
|
|
jlabel[i + r][j + c].setVisible(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void openAllCell() {
|
|
|
|
|
// TODO Auto-generated method stub
|
|
|
|
|
for (int i = 0; i < rows; i++) {
|
|
|
|
|
for (int j = 0; j < cols; j++) {
|
|
|
|
|
buts[i][j].setVisible(false);
|
|
|
|
|
jlabel[i][j].setVisible(true);
|
|
|
|
|
click[i][j] = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void initLable() {
|
|
|
|
|
for (int i = 0; i < rows; i++) {
|
|
|
|
|
for (int j = 0; j < cols; j++) {
|
|
|
|
|
JLabel l = new JLabel("", JLabel.CENTER);
|
|
|
|
|
l.setBounds(j * BLOCKWIDTH, i * BLOCKHEIGHT, BLOCKWIDTH, BLOCKHEIGHT);// 设置每个小方格的位置大小
|
|
|
|
|
l.setBorder(BorderFactory.createLineBorder(Color.gray));// 绘制方格边框为灰色
|
|
|
|
|
l.setOpaque(true);// 设置方格为透明,方便我们填充
|
|
|
|
|
l.setBackground(Color.lightGray);// 背景填充为浅灰色
|
|
|
|
|
this.add(l);// 添加到面板中
|
|
|
|
|
jlabel[i][j] = l;// 将方格加到类变量中,方便公用
|
|
|
|
|
l.setVisible(false);// 设置不可见
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void buryMines() {// 生成雷区
|
|
|
|
|
for (int i = 0; i < minesCount; i++) {
|
|
|
|
|
int x = (int) (Math.random() * rows);// 生成随机行数
|
|
|
|
|
int y = (int) (Math.random() * cols);// 生成随机列数
|
|
|
|
|
/* 判断随机生成的位置是不是有地雷 */
|
|
|
|
|
if (state[x][y] == true) {// 如果随机生成的位置上已经有雷了,则i--
|
|
|
|
|
i--;
|
|
|
|
|
} else {// 位置上没有雷,则state为true,标签设置为雷
|
|
|
|
|
state[x][y] = true;
|
|
|
|
|
jlabel[x][y].setText("雷");
|
|
|
|
|
// buts[x][y].setText("雷");// 调式代码用
|
|
|
|
|
// System.out.println(x + "," + y + ":位置有地雷");//调式代码用
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private int rows, cols, minesCount;
|
|
|
|
|
private final int BLOCKWIDTH = 30;
|
|
|
|
|
private final int BLOCKHEIGHT = 30;
|
|
|
|
|
private Buts[][] buts;
|
|
|
|
|
private JLabel[][] jlabel;
|
|
|
|
|
private boolean[][] state;
|
|
|
|
|
private int[][] click;
|
|
|
|
|
private ImageIcon mineIcon;
|
|
|
|
|
|
|
|
|
|
public GamePanel(int row, int col) {
|
|
|
|
|
rows = row;
|
|
|
|
|
cols = col;
|
|
|
|
|
minesCount = rows * cols / 10;
|
|
|
|
|
MineSweeper.setMineNum(minesCount);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
mineIcon = new ImageIcon(ImageIO.read(new File("mine.png")));
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 缩放图标到合适大小
|
|
|
|
|
Image scaledImage = mineIcon.getImage().getScaledInstance(
|
|
|
|
|
BLOCKWIDTH, BLOCKHEIGHT, Image.SCALE_SMOOTH);
|
|
|
|
|
mineIcon = new ImageIcon(scaledImage);
|
|
|
|
|
|
|
|
|
|
buts = new Buts[rows][cols];
|
|
|
|
|
jlabel = new JLabel[rows][cols];
|
|
|
|
|
state = new boolean[rows][cols];
|
|
|
|
|
click = new int[rows][cols];
|
|
|
|
|
|
|
|
|
|
setLayout(null);
|
|
|
|
|
initButtons();
|
|
|
|
|
initLable();
|
|
|
|
|
buryMines();
|
|
|
|
|
writerNumber();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void writerNumber() {
|
|
|
|
|
for (int i = 0; i < rows; i++) {
|
|
|
|
|
for (int j = 0; j < cols; j++) {
|
|
|
|
|
if (!state[i][j]) {
|
|
|
|
|
int numbers = 0;
|
|
|
|
|
for (int r = -1; r < 2; r++) {
|
|
|
|
|
for (int c = -1; c < 2; c++) {
|
|
|
|
|
if ((i + r > -1) && (i + r < cols) && (j + c > -1) && (j + c < rows)) {
|
|
|
|
|
if (state[i + r][j + c]) numbers++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (numbers > 0) {
|
|
|
|
|
click[i][j] = 2;
|
|
|
|
|
}
|
|
|
|
|
jlabel[i][j].setText(String.valueOf(numbers));
|
|
|
|
|
jlabel[i][j].setIcon(null); // 确保数字位置不显示图标
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void initButtons() {
|
|
|
|
|
for (int i = 0; i < rows; i++) {
|
|
|
|
|
for (int j = 0; j < cols; j++) {
|
|
|
|
|
Buts but = new Buts();
|
|
|
|
|
but.i = i;
|
|
|
|
|
but.j = j;
|
|
|
|
|
but.setBounds(BLOCKWIDTH * j, BLOCKHEIGHT * i, BLOCKWIDTH, BLOCKHEIGHT);
|
|
|
|
|
but.setMargin(new Insets(0, 0, 0, 0));
|
|
|
|
|
|
|
|
|
|
but.addMouseListener(new MouseAdapter() {
|
|
|
|
|
@Override
|
|
|
|
|
public void mouseClicked(MouseEvent e) {
|
|
|
|
|
if (e.getButton() == MouseEvent.BUTTON1) {
|
|
|
|
|
openButtons(but);
|
|
|
|
|
}
|
|
|
|
|
if (e.getButton() == MouseEvent.BUTTON3) {
|
|
|
|
|
placeFlag(but);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
buts[i][j] = but;
|
|
|
|
|
this.add(buts[i][j]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void placeFlag(Buts but) {
|
|
|
|
|
if (click[but.i][but.j] != 3) {
|
|
|
|
|
buts[but.i][but.j].setText("旗");
|
|
|
|
|
click[but.i][but.j] = 3;
|
|
|
|
|
minesCount--;
|
|
|
|
|
MineSweeper.setMineNum(minesCount);
|
|
|
|
|
} else {
|
|
|
|
|
buts[but.i][but.j].setText("");
|
|
|
|
|
if (!state[but.i][but.j]) {
|
|
|
|
|
if (Integer.valueOf(jlabel[but.i][but.j].getText()) > 0) {
|
|
|
|
|
click[but.i][but.j] = 2;
|
|
|
|
|
} else {
|
|
|
|
|
click[but.i][but.j] = 0;
|
|
|
|
|
}
|
|
|
|
|
minesCount++;
|
|
|
|
|
MineSweeper.setMineNum(minesCount);
|
|
|
|
|
} else {
|
|
|
|
|
click[but.i][but.j] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (minesCount == 0) {
|
|
|
|
|
boolean flag = true;
|
|
|
|
|
for (int i = 0; i < rows; i++) {
|
|
|
|
|
for (int j = 0; j < cols; j++) {
|
|
|
|
|
if ((click[i][j] != 3) && state[i][j]) {
|
|
|
|
|
flag = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
MineSweeper.cd.stop();
|
|
|
|
|
JOptionPane.showMessageDialog(null, flag ? "您成功了" : "旗子已经用完", "游戏结束", JOptionPane.PLAIN_MESSAGE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void openButtons(Buts but) {
|
|
|
|
|
int i = but.i;
|
|
|
|
|
int j = but.j;
|
|
|
|
|
|
|
|
|
|
if (state[i][j] && (click[i][j] != 3)) {
|
|
|
|
|
openAllCell();
|
|
|
|
|
MineSweeper.cd.stop();
|
|
|
|
|
JOptionPane.showMessageDialog(null, "您踩到地雷了", "游戏结束", JOptionPane.PLAIN_MESSAGE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (click[i][j] == 2) {
|
|
|
|
|
buts[i][j].setVisible(false);
|
|
|
|
|
jlabel[i][j].setVisible(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((click[i][j] == 0) || (click[i][j] == 1)) {
|
|
|
|
|
for (int r = -1; r < 2; r++) {
|
|
|
|
|
for (int c = -1; c < 2; c++) {
|
|
|
|
|
if ((i + r > -1) && (i + r < cols) && (j + c > -1) && (j + c < rows)
|
|
|
|
|
&& (!state[i + r][j + c])) {
|
|
|
|
|
|
|
|
|
|
if (click[i + r][j + c] == 0) {
|
|
|
|
|
buts[i + r][j + c].setVisible(false);
|
|
|
|
|
jlabel[i + r][j + c].setVisible(true);
|
|
|
|
|
click[i + r][j + c] = 1;
|
|
|
|
|
openButtons(buts[i + r][j + c]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (click[i + r][j + c] == 2) {
|
|
|
|
|
buts[i + r][j + c].setVisible(false);
|
|
|
|
|
jlabel[i + r][j + c].setVisible(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void openAllCell() {
|
|
|
|
|
for (int i = 0; i < rows; i++) {
|
|
|
|
|
for (int j = 0; j < cols; j++) {
|
|
|
|
|
buts[i][j].setVisible(false);
|
|
|
|
|
jlabel[i][j].setVisible(true);
|
|
|
|
|
if (state[i][j]) {
|
|
|
|
|
jlabel[i][j].setIcon(mineIcon);
|
|
|
|
|
}
|
|
|
|
|
click[i][j] = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void initLable() {
|
|
|
|
|
for (int i = 0; i < rows; i++) {
|
|
|
|
|
for (int j = 0; j < cols; j++) {
|
|
|
|
|
JLabel l = new JLabel("", JLabel.CENTER);
|
|
|
|
|
l.setBounds(j * BLOCKWIDTH, i * BLOCKHEIGHT, BLOCKWIDTH, BLOCKHEIGHT);
|
|
|
|
|
l.setBorder(BorderFactory.createLineBorder(Color.gray));
|
|
|
|
|
l.setOpaque(true);
|
|
|
|
|
l.setBackground(Color.lightGray);
|
|
|
|
|
l.setHorizontalTextPosition(SwingConstants.CENTER);
|
|
|
|
|
l.setVerticalTextPosition(SwingConstants.CENTER);
|
|
|
|
|
this.add(l);
|
|
|
|
|
jlabel[i][j] = l;
|
|
|
|
|
l.setVisible(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void buryMines() {
|
|
|
|
|
for (int i = 0; i < minesCount; i++) {
|
|
|
|
|
int x = (int) (Math.random() * rows);
|
|
|
|
|
int y = (int) (Math.random() * cols);
|
|
|
|
|
if (!state[x][y]) {
|
|
|
|
|
state[x][y] = true;
|
|
|
|
|
jlabel[x][y].setIcon(mineIcon);
|
|
|
|
|
jlabel[x][y].setText("");
|
|
|
|
|
} else {
|
|
|
|
|
i--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Buts extends JButton {
|
|
|
|
|
public int i, j;
|
|
|
|
|
public int i, j;
|
|
|
|
|
}
|