用Java来开发了以下经典小游戏扫雷,作为学习Java Swing的练手。
主要代码是有三个类:setting类存放游戏的一些设定,Map是new一个游戏开始的框架,MapFrame是游戏框架以及响应点击等方法。
以下是3个类的代码,初学者写的代码难免有许多不成熟的地方,请各位轻喷。
setting
1 package map; 2 3 public class Setting { 4 public int row; 5 public int col; 6 public int mine; 7 public Setting(int row,int col,int mine) { 8 this.row=row; 9 this.col=col; 10 this.mine=mine; 11 } 12 }
Map
1 package map; 2 3 import java.awt.*; 4 import javax.swing.*; 5 import java.util.Random; 6 7 public class Map { 8 public static final int[] dx=new int[]{-1,-1,-1,0,1,1,1,0}; 9 public static final int[] dy=new int[]{-1,0,1,1,1,0,-1,-1}; 10 public Setting setting; 11 public int[][] map; 12 13 public Map() { 14 NewMap(); 15 } 16 17 public static void NewMap() { 18 Setting setting=new Setting(9,9,10); 19 EventQueue.invokeLater(()->{ 20 JFrame frame=new MapFrame(setting); 21 frame.setTitle("Minesweeper"); 22 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 23 frame.setVisible(true); 24 }); 25 } 26 }
MapFrame
1 package map; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.awt.geom.*; 6 7 import javax.swing.*; 8 import javax.swing.border.Border; 9 10 import java.util.LinkedList; 11 import java.util.Queue; 12 import java.util.Random; 13 14 public class MapFrame extends JFrame { 15 public int row,col,mine; 16 public int[][] map; 17 public boolean[][] visit; 18 public JButton[][] mine_button; 19 public static final int[] dx=new int[] {-1,0,1,0,-1,-1,1,1}; 20 public static final int[] dy=new int[] {0,1,0,-1,-1,1,1,-1}; 21 22 public int total_visit; 23 24 public MapFrame(Setting setting) { 25 this.row=setting.row; this.col=setting.col; this.mine=setting.mine; 26 this.map=calc_map(setting); 27 mine_button=new JButton[row][col]; 28 visit=new boolean[row][col]; 29 total_visit=0; 30 int fwidth=row/9*400,fheight=col/9*400+70; 31 setSize(fwidth,fheight); 32 JPanel TimeJpanel=new JPanel(); 33 JPanel MapJpanel=new JPanel(); 34 35 JLabel TimeText=new JLabel("Time : 0"); 36 TimeJpanel.add(TimeText); 37 38 myTimer timer =new myTimer(TimeText); 39 Timer timelistener =new Timer(1000,timer); 40 timelistener.start(); //开始定时器 41 42 MapJpanel.setPreferredSize(new Dimension(row/9*400,col/9*400)); 43 MapJpanel.setLayout(new GridLayout(row,col)); 44 for (int i=0;i<row*col;i++) { 45 int x=i/this.col; 46 int y=i%this.row; 47 mine_button[x][y]=new JButton(); 48 mine_button[x][y].setBackground(new Color(81,168,221)); 49 mine_button[x][y].addActionListener(new click_listener(x,y)); 50 MapJpanel.add(mine_button[x][y]); 51 } 52 53 setLayout(new BorderLayout()); 54 add(TimeJpanel,BorderLayout.NORTH); 55 add(MapJpanel,BorderLayout.SOUTH); 56 } 57 58 class click_listener implements ActionListener { 59 public int x,y; 60 public click_listener(int x,int y) { 61 this.x=x; this.y=y; 62 } 63 64 public void actionPerformed(ActionEvent event) { 65 if (visit[this.x][this.y]) return; 66 int num=map[this.x][this.y]; 67 if (num!=-1) { 68 mine_button[this.x][this.y].setBackground(Color.WHITE); 69 if (num==0) whitebfs(this.x,this.y); 70 else { 71 if (!visit[this.x][this.y]) total_visit++; visit[this.x][this.y]=true; 72 mine_button[this.x][this.y].setText(""+num); 73 } 74 if (total_visit+mine==row*col) { 75 //游戏成功 76 int selection=JOptionPane.showConfirmDialog(null,"你成功排掉所有雷,是否重新开始?","游戏成功", 77 JOptionPane.OK_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE); 78 if (selection==JOptionPane.YES_OPTION) { 79 //重新开始游戏 80 dispose(); 81 Map.NewMap(); 82 } 83 } 84 } else { 85 //游戏失败 86 mine_button[this.x][this.y].setIcon(new ImageIcon("./Image/mine.jpg")); 87 int selection=JOptionPane.showConfirmDialog(null,"你踩到雷了,是否重新开始?","游戏失败", 88 JOptionPane.OK_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE); 89 if (selection==JOptionPane.YES_OPTION) { 90 //重新开始游戏 91 dispose(); 92 Map.NewMap(); 93 } 94 } 95 } 96 97 public void whitebfs(int x,int y) { 98 Queue<Integer> q=new LinkedList<>(); 99 q.offer(x*col+y); 100 while (q.size()>0) { 101 int now=q.poll(); 102 x=now/col; y=now%col; 103 if (!visit[x][y]) total_visit++; visit[x][y]=true; 104 mine_button[x][y].setBackground(Color.WHITE); 105 around(x,y); 106 for (int i=0;i<4;i++) { 107 int tx=x+dx[i],ty=y+dy[i]; 108 if (tx<0 || tx>=row || ty<0 || ty>=col) continue; 109 if (visit[tx][ty]) continue; 110 if (map[tx][ty]!=0) continue; 111 q.offer(tx*col+ty); 112 } 113 } 114 } 115 116 public void around(int x,int y) { 117 for (int i=0;i<8;i++) { 118 int tx=x+dx[i],ty=y+dy[i]; 119 if (tx<0 || tx>=row || ty<0 || ty>=col) continue; 120 if (map[tx][ty]>0) { 121 if (!visit[tx][ty]) total_visit++; visit[tx][ty]=true; 122 mine_button[tx][ty].setBackground(Color.WHITE); 123 if (map[tx][ty]>0)mine_button[tx][ty].setText(""+map[tx][ty]); 124 } 125 } 126 } 127 } 128 129 /** 130 * 计时器 131 */ 132 class myTimer implements ActionListener { 133 JLabel text; 134 long start; 135 public myTimer(JLabel text) { 136 this.text=text; 137 start=System.currentTimeMillis(); 138 } 139 public void actionPerformed(ActionEvent event) { 140 text.setText("Time : "+(System.currentTimeMillis()-start)/1000); 141 } 142 } 143 144 /** 145 * 计算map数字大小 146 */ 147 public int[][] calc_map(Setting setting) { 148 int[][] map=new int[setting.row+2][setting.col+2]; 149 for (int i=0;i<=setting.row+1;i++) 150 for (int j=0;j<=setting.col+1;j++) 151 map[i][j]=0; 152 153 int now_mine=0; 154 Random rand=new Random(System.currentTimeMillis()); 155 while (now_mine<setting.mine) { 156 int mine_x=rand.nextInt(setting.row); 157 int mine_y=rand.nextInt(setting.col); 158 if (map[mine_x][mine_y]==0) { 159 map[mine_x][mine_y]=-1; 160 now_mine++; 161 } 162 } 163 164 for (int i=1;i<=setting.row;i++) 165 for (int j=1;j<=setting.col;j++) { 166 if (map[i][j]==-1) continue; 167 for (int k=0;k<8;k++) map[i][j]+=(map[i+dx[k]][j+dy[k]]==-1 ? 1 : 0); 168 } 169 170 return map; 171 } 172 }