〇、目錄
- 一、前言
- 二、程序中遇到的困難
- 三、代碼
- 四、成品圖
- 五、代碼存在的bug
- 六、完善建議
- 七、結語
一、前言
這個學期學習了Java,課程的最后一項作業就是做一個掃雷游戲和一個計算器,經歷一段時間的煎熬終于做出來了,就想來分享一下我的喜悅和成果,
在老師布置作業后,我的計算器代碼就根據老師黑板上代碼微調后很快就收工了,而這個掃雷也是有了明確的思路,但是卻找不到相對應的代碼來實作,后來在百度上看了一位前輩的掃雷代碼終于解決了我問題,這里是那位前輩的掃雷代碼鏈接
其實回過頭來看,我寫這個代碼確實極其簡陋,相比我在百度上找的各種大佬做出來的掃雷,感覺差距極大,但是想想是我自己做出來的還是很高興的,但是也明白我還只是個小白,
二、程序中遇到的困難
老師一布置作業我就想出來了一個做法,那就是做兩層組件,底層是label,可以用來顯示數字和雷,如下圖所示這樣的效果,其中"!"表示隨機生成的雷,

再在這上面蓋一層相同數量button組件,點擊一個button,這個button就消失,顯示出下層的label,
當我開始寫代碼時,我就卡在了這一步,我定義一個panel并設定了20*20的gridlayout(網格布局),當我添加進去400個label時,成功達到了上圖的底層效果,但是當我再添加400個button時,就出現問題了,這個button不會重疊到label上面,而是繼續向下排列,和label處于了同一層,然后百度了好久都沒有解決問題,最后決定看看別人的代碼是怎么做的,最后看了某位前輩的作品,原來他是清除了panel原有的layout,用坐標放置組件,這樣就可以重疊了,于是后面我就很快的寫好了,
(也許這個問題也有其他的解決方法,我感覺用gridlayout也可以做出的,知道怎么做的大佬可以說一下)
三、代碼
最重要的代碼來了
package testone;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
public class Try1 {
JFrame f;
JPanel p,p1,p2;
int n = 20; //掃雷正方形界面的的邊長(只能手動修改控制難度)
int boomnumber = 50; //設定雷的個數(只能手動修改控制難度)后續可以添加按鍵修改難度
JButton zuobi,restart; //作弊和重新開始的按鈕
JButton b[][] = new JButton[n][n];
JLabel l[][] = new JLabel[n][n]; //下層顯示的label
int boxy[][]; //存盤雷的橫縱坐標的陣列
int visited[][] = new int[n][n]; //被訪問記錄,訪問過為1
Try1() {
f = new JFrame("掃雷");
f.setBounds(600, 200, 495, 545);
p = new JPanel(); //掃雷游戲面板
p.setLayout(null); //清除原有的layout,后面使用坐標放置組件
p1 = new JPanel(); //最底層面板
p2 = new JPanel(); //放置功能按鍵的面板
p1.setLayout(new BorderLayout());
p2.setLayout(new GridLayout(1,3)); //網格布局,一行三列
p.setBackground(new Color(193, 210, 240));
makeboom(n, p); //自己定義的函式,生成雷和陣列label的
makebutton(n, p); //生成掃雷按鈕的,會覆寫在底層label上
zuobi =new JButton("作弊");
zuobi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for (int i[]:boxy) {
b[i[0]][i[1]].setText(".");
}
}
});
restart = new JButton("重新開始");
restart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
f.dispose(); //關閉
new Try1();
}
});
p1.add(p,BorderLayout.CENTER);
p1.add(p2,BorderLayout.NORTH);
p2.add(restart);
p2.add(zuobi);
f.add(p1);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void makebutton(int n, JPanel a) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
a.add(b[i][j] = new JButton());
b[i][j].setBounds(j * 24, i * 24, 24, 24);
b[i][j].addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
JButton d = (JButton) e.getSource();
int index = 0;
int indey = 0;
for (int i = 0; i < n; i++) { //獲取點擊的按鈕的坐標
for (int j = 0; j < n; j++) {
if (d == b[i][j]) {
index = i;
indey = j;
}
}
}
open(index,indey);
}
});
}
}
}
public void makeboom(int n, JPanel a) {
boxy = boom(n, boomnumber);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
l[i][j] = new JLabel("0", JLabel.CENTER);
l[i][j].setBounds(j * 24, i * 24, 24, 24);
l[i][j].setBorder(BorderFactory.createLineBorder(Color.GRAY));
l[i][j].setOpaque(true);
l[i][j].setVisible(false);
a.add(l[i][j]);
}
}
for (int i = 0; i < boomnumber; i++) {
l[boxy[i][0]][boxy[i][1]].setText("!");
visited[boxy[i][0]][boxy[i][1]] = 1;
}
setshuzi();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if(l[i][j].getText().equals("0")) {
l[i][j].setText("");
}
}
}
}
public int[][] boom(int n, int m) { // n是網格最大長寬,m是雷的個數
int[][] boxy = new int[m][2];
int cishu = 0;
while (cishu != m) {
int x = (int)(Math.random() * n);
int y = (int)(Math.random() * n);
if(isrepeat(x,y,boxy,cishu) == 0){
boxy[cishu][0] = x;
boxy[cishu][1] = y;
cishu++;
}
}
return boxy;
}
public int isrepeat(int x, int y, int a[][], int cishu) {
int is = 0;
for (int i = 0; i < cishu; i++) {
if (a[i][0] == x && a[i][1] == y) {
is = 1;
break;
} else {
is = 0;
}
}
return is;
}
public void setshuzi() {
for (int[] i:boxy) {
int x = i[0];
int y = i[1];
for(int u = x-1;u<x+2;u++) {
for(int v = y-1;v<y+2;v++) {
if(u>=0&&u<n&&v>=0&&v<n) {
String s = l[u][v].getText();
if(!s.equals("!")) {
int lnumb = Integer.parseInt(s);
lnumb ++;
l[u][v].setText(lnumb+"");
}
}
}
}
}
}
public void open(int x,int y) {
b[x][y].setVisible(false);
l[x][y].setVisible(true);
visited[x][y]=1;
if(iswin()) {
JOptionPane.showMessageDialog(null,"游戲獲勝","游戲獲勝",JOptionPane.PLAIN_MESSAGE);
}else {
if(l[x][y].getText().equals("!")) {
JOptionPane.showMessageDialog(null,"您失敗了","游戲結束",JOptionPane.PLAIN_MESSAGE);
}else if(l[x][y].getText().equals("")){
for(int u = x-1;u<x+2;u++) {
for(int v = y-1;v<y+2;v++) {
if(u>=0&&u<n&&v>=0&&v<n&&visited[u][v]!=1) {
open(u,v);
}
}
}
}else {
}
}
}
public boolean iswin() {
int last =-1;
for(int i[]:visited) {
if(Arrays.binarySearch(i, 0)< 0) {
last = 1;
}else {//只要存在1個沒有訪問的,就判定沒有贏,退出回圈
last = -1;
break;
}
}
if(last==1) {
return true;
}else {
return false;
}
}
public static void main(String[] args) {
Try1 t = new Try1();
}
}
四、成品圖

五、代碼存在的bug
1.游戲獲勝判斷提前:
游戲獲勝判斷每次點擊按鈕都要判斷的,如果所有的位置都被訪問過即可獲勝(其中生成雷的位置提在生成雷時編輯為訪問過的狀態),但是在還未全部點擊的情況,就會提醒游戲獲勝,
2.游戲失敗還能繼續游戲:
這個問題可以解決,但是由于本人太懶了沒寫,只要在踩雷后使所有button不可見即可,
3.未知…(等待讀者發現)
六、完善建議
1.雷的顏色可以設定高亮顏色,踩雷后更醒目,
2.添加可控難度的按鈕,可以放到選單欄,
3.設定插旗子的功能,如果可以的話,最好用圖片而不是字符,
七、結語
歡迎評論留言交流,有錯誤或者修改建議請評論留言,可能回復不及時請見諒,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/240132.html
標籤:其他
