本文实例为大家分享了Java Swing实现扫雷源码的具体代码,供大家参考,具体内容如下
先来看下效果
运行时只需要创建一个GameWindow的对象即可,可使用有参构造函数自定义雷区行列数及炸弹个数,也可使用无参构造函数设置默认值(小旗和炸弹的图标自己去找吧,我就不在这里放了)
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.LinkedList;
public class GameWindow{
private static Font labelFont = new Font("隶书",Font.BOLD,45);
private static Font buttonFont = new Font("隶书",Font.CENTER_BASELINE,20);
private static Icon flag = new ImageIcon("src/images/小旗.jpg");//小旗图标
private static Icon bomb = new ImageIcon("src/images/炸弹.png");//炸弹图标
private static int labelWeight = 30;//小方块(雷区)宽度
private static int labelHeigth = 30;//小方块(雷区)高度
private static int labelSpace = 1;//小方块(雷区)间距
private static int scoreHeight = 50;//积分区域高度
private static int[] x8 = {-1,-1,-1,0,0,1,1,1};//原坐标周围 8 个坐标的 x 值变化
private static int[] y8 = {-1,0,1,-1,1,-1,0,1};//原坐标周围 8 个坐标的 y 值变化
private static int[] x4 = {0,0,1,-1};//原坐标周围 4 个坐标的 x 值变化
private static int[] y4 = {1,-1,0,0};//原坐标周围 4 个坐标的 x 值变化
private JFrame frame;
private int[][] data;//存储和炸弹位置有关数据,值为-1时表示炸弹
private JLabel[][] labels;
private JPanel mainPanel;//雷区主面板
private JPanel scorePanel;//积分区域面板
private JLabel areaLabel;//未扫雷区个数标签
private JLabel bombLabel;//剩余地雷数标签
private int width;//窗体宽度
private int height;//窗体高度
private int row;//行数
private int column;//列数
private int bombNum;//炸弹个数
private int remainArea;//未扫雷区个数
private int remainBomb;//剩余地雷数
public GameWindow(int row,int column,int bombNum){
frame = new JFrame("扫雷-洋仔小游戏");
this.row = row;
this.column = column;
this.bombNum = bombNum;
mainPanel = new JPanel();
init();
}
public GameWindow(){
this(10,10,20);
}
private void setWidthAndHeight(){
width = labelWeight * column + (column + 1) * labelSpace;
height = scoreHeight + labelHeigth * row + (row + 1) * labelSpace;
}
private void setBomb(){
if(bombNum > row * column)
throw new RuntimeException("炸弹数设置过多!");
data = new int[row][column];
int count = 0;
while (count < bombNum){
int r = (int)(Math.random() * row);
int c = (int)(Math.random() * column);
System.out.println("r = " + r + "\tc = " + c);
if(data[r][c] == -1)
continue;
data[r][c] = -1;
for(int i = 0; i < 8; i ++){
int x = r + x8[i];
int y = c + y8[i];
if(x < 0 || x >= row || y < 0 || y >= column || data[x][y] == -1)
continue;
data[r + x8[i]][c + y8[i]] ++;
}
count ++;
System.out.println(count);
}
}
private class ButtonListener extends MouseAdapter {
private JButton button;
private int r;
private int w;
private GameWindow window;
private boolean disabled = true;
public ButtonListener(JButton button,int r,int w,GameWindow window){
this.button = button;
this.r = r;
this.w = w;
this.window = window;
}
@Override
public void mouseClicked(MouseEvent mouseEvent) {
synchronized (window){
if(!button.isEnabled())
return;
if(mouseEvent.getButton() == MouseEvent.BUTTON3){
if(disabled) {
button.setIcon(flag);
data[r][w] -= 20;
remainBomb --;
remainArea --;
}
else {
button.setIcon(null);
data[r][w] += 20;
remainBomb ++;
remainArea ++;
}
disabled = !disabled;
bombLabel.setText("" + remainBomb);
areaLabel.setText("" + remainArea);
return;
}
if(!disabled)
return;
int cnt = 1;
button.setVisible(false);
if(data[r][w] == -1){
gameOver();
// System.out.println("\n点到炸弹,全体按钮已禁用");
return;
}
LinkedList<int[]> stack = new LinkedList<>();
stack.push(new int[]{r,w});
data[r][w] = -1;
while (stack.size() > 0){
int[] source = stack.pop();
for(int i = 0; i < 4; i ++){
int x = source[0] + x4[i];
int y = source[1] + y4[i];
if(x < 0 || x >= row || y < 0 || y >= column || data[x][y] < 0)
continue;
if(data[x][y] == 0)
stack.push(new int[]{x,y});
labels[x][y].getLabelFor().setVisible(false);
cnt ++;
data[x][y] = -1;
}
}
remainArea -= cnt;
areaLabel.setText("" + remainArea);
if(remainArea == remainBomb){
gameOver();
}
}
}
}
private void gameOver(){
for(JLabel[] ls : labels){
for(JLabel l : ls){
JButton button = (JButton) l.getLabelFor();
button.setEnabled(false);
}
}
}
private void init(){
setWidthAndHeight();
frame.setBounds(380,100,width + 9,height + 32);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLayout(null);
mainPanel.setBackground(Color.GRAY);
mainPanel.setBounds(1,scoreHeight + 1,width,height);
mainPanel.setLayout(null);
scorePanel = new JPanel();
scorePanel.setBounds(0,0,width,scoreHeight);
scorePanel.setLayout(new GridLayout(1,3,0,0));
areaLabel = new JLabel();
areaLabel.setFont(labelFont);
areaLabel.setHorizontalAlignment(JLabel.CENTER);
scorePanel.add(areaLabel);
JLabel buttonLabel = new JLabel();
scorePanel.add(buttonLabel);
JButton resetButton = new JButton("重开");
resetButton.setFont(buttonFont);
resetButton.setFocusPainted(false);
resetButton.setBounds(width/ 24,10,width / 4,30);
resetButton.addActionListener((event)->{
frame.setVisible(false);
mainPanel.removeAll();
resetGame();
});
buttonLabel.add(resetButton);
bombLabel = new JLabel();
bombLabel.setFont(labelFont);
bombLabel.setHorizontalAlignment(JLabel.CENTER);
scorePanel.add(bombLabel);
frame.add(scorePanel);
frame.add(mainPanel);
resetGame();
}
public void resetGame(){
setBomb();
remainArea = row * column;
remainBomb = bombNum;
labels = new JLabel[row][column];
System.gc();
for(int i = 0; i < row; i ++){
for(int j = 0; j < column; j ++){
labels[i][j] = new JLabel();
//设置元素居中
labels[i][j].setHorizontalAlignment(JLabel.CENTER);
if(data[i][j] == -1) {
labels[i][j].setIcon(bomb);
}
else if(data[i][j] > 0)
labels[i][j].setText("" + data[i][j]);
int y = (i + 1) * labelSpace + i * labelWeight;
int x = (j + 1) * labelSpace + j * labelHeigth;
labels[i][j].setBounds(x,y,labelWeight,labelHeigth);
JButton button = new JButton();
button.addMouseListener(new ButtonListener(button,i,j,this));
button.setBounds(0,0,labelWeight,labelHeigth);
labels[i][j].setLayout(null);
labels[i][j].add(button);
labels[i][j].setLabelFor(button);
mainPanel.add(labels[i][j]);
}
}
areaLabel.setText("" + remainArea);
bombLabel.setText("" + remainBomb);
frame.setVisible(true);
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。