Java Swing扫雷源码
掉队洋先生 人气:0先来看下效果
运行时只需要创建一个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); } }
加载全部内容