ava類庫中提供了用于GUI的swing開發工具包,我們可以利用swing設計出一些簡單的經典小遊戲,如掃雷,推箱子,俄羅斯方塊等.接下來我就簡單分享一下用Java設計掃雷遊戲的思路與過程.
首先,我們要設計出掃雷的視窗界面,說白了,也就是在視窗上繪制出指定行數和列數的小方格.要在窗體上繪制方格,我們需要一個JPanel面闆,是以我們定義類GamePanel讓它繼承自JPanel,然後我們在就可以這個類上繪制我們所要的資訊了.然後,在類中,我們定義一些基本的變量,如行數,列數,雷的數量等等,友善後面使用
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class GamePanel extends JPanel {
private static final long serialVersionUID = 1L;
// 界面行數
private int rows;
// 界面列數
private int cols;
// 炸彈數
private int bombCount;
// 每個方格寬度
private final int BLOCKWIDTH = 20;
// 每個方格長度
private final int BLOCKHEIGHT = 20;
// 存儲界面中每一個方格的繪制資訊
private JLabel[][] labels;
}
(JLabel标簽用于短文本字元串或圖像或二者的顯示區,我們用它來顯示方格邊界,數字,或者雷等資訊)
接下來我們在構造方法中初始化這些類變量
// 構造方法,初始化參數
public GamePanel(int rows, int cols) {
this.rows = rows;
this.cols = cols;
this.bombCount = rows * cols / 10;
this.labels = new JLabel[rows][cols];
this.setLayout(null);
}
然後,我們就可以在這個JPanel面闆上繪制小方格了.我們先建立一個名為initLabels()的方法,在這個方法中根據行數和列數循環産生JLabel标簽,并将每個标簽的邊界繪制出來,填充背景并将它們存儲到類二維數組變量 labels中,這樣,我們就得到了一個充滿小方格的掃雷窗體
// 界面初始化,繪制掃雷的邊框
private void initLabels(){
for (int i = 0; i < this.rows; i++) {
for (int j = 0; j < this.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.YELLOW);
// 将方格加入到容器中(即面闆JPanel)
this.add(l);
// 将方格存到類變量中,友善公用
labels[i][j] = l;
}
}
}
然後在構造方法中調用這個初始化方法
當我們将這個JPanel面闆繪制完後,我們還要将它放在一個JFrame容器中它才能顯示出來,這樣我們就需要将JPanel的大小作為參數傳出去,友善設定容器的大小,是以我們再定義一個public的方法,計算寬和高,并以數組的形式傳遞出去
import java.awt.Container;
import javax.swing.JFrame;
public class Game {
public static void main(String[] args) {
// 建立JFrame對象作為容器
JFrame w = new JFrame();
// 建立mainPanel對象,初始化一個20*30的方格窗體
GamePanel mainPanel = new GamePanel(20, 30);
// 擷取JFrame應給設定的寬度和高度
int[] a = mainPanel.returnSize();
// 設定JFame寬和高
w.setSize(a[0], a[1]);
Container c = w.getContentPane();
c.add(mainPanel);
w.setVisible(true);
}
}
運作程式,結果如下

這樣,我們第一階段的工作就完成了.接下來,我們要在上面這個圖中産生bombCount個炸彈,也就是在我們生成的labels中随機挑選出bombCount個炸彈,并用"*"顯示出來
// 産生bombCount個炸彈,并在labels中用"*"标注出來
private void randomBomb() {
for (int i = 0; i < this.bombCount; i++) {
// 生成一個随機數表示行坐标
int rRow = (int) (Math.random() * this.rows);
// 生成一個随機數表示列坐标
int rCol = (int) (Math.random() * this.cols);
// 根據坐标确定JLabel的位置,并顯示*
this.labels[rRow][rCol].setText("*");
// 設定背景顔色
this.labels[rRow][rCol].setBackground(Color.DARK_GRAY);
// 設定*的顔色
this.labels[rRow][rCol].setForeground(Color.RED);
}
}
然後我們在initLabels()方法中調用randomBomb()這個方法,運作程式,顯示如下:
至此,我們已經完成了掃雷遊戲的一半程式,隻剩下填充按鈕和點選按鈕後發生的邏輯判斷了,我們已經将掃雷的繪制了方格陣列并随機配置設定了炸彈的位置,接下來我們要将陣列全部覆寫上按鈕.因為我們要通過按鈕來獲知目前方格的坐标,是以簡單的Button按鈕還無法滿足我們的要求,是以,我們就自定義一個按鈕的類,讓它繼承自Button類,但要給他加上行号和列号,這樣我們就能直接通過按鈕讀取它的位置了
import javax.swing.JButton;
public class MyButton extends JButton {
private static final long serialVersionUID = 1L;
protected int row;
protected int col;
}
然後我們就可以在GamePanel類中添加按鈕了
// 初始化按鈕,将JLabel覆寫住
private void initButtons() {
// 循環生成按鈕
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
MyButton btn = new MyButton();
// 根據JLabel大小設定按鈕的大小邊界
btn.setBounds(j * BLOCKWIDTH, i * BLOCKHEIGHT, BLOCKWIDTH, BLOCKHEIGHT);
this.add(btn);
// 将按鈕存在類變量中(當然,實際上存的是對象的引用位址)
buttons[i][j] = btn;
btn.row = i;
btn.col = j;
// 給按鈕添加監聽器,注冊點選事件
// (單機按鈕時,将執行内部類ActionListener()中的actionPerformed(ActionEvent e)方法)
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}});
}
}
}
按鈕全部覆寫以後,顯示如下:
最後,我們就差單擊按鈕後判斷按鈕底下是炸彈,空白,還是數字,如果下面是數字的話,我們就打開按鈕(也就是将按鈕設定為不可見,就可以看見JLabel了); 如果單擊的按鈕下面是空白的話先要将它打開,并且判斷它周圍的八個方塊是否為空的,進入遞歸調用.
首先,要判斷每個小方塊周圍的八個方塊,就要先判斷它是否越界,我們設為一個類變量作為坐标偏移量
判斷是否越界:
// 判斷位置是否越界
private boolean verify(int row, int col) {
return row >= 0 && row < this.rows && col >= 0 && col < this.cols;
}
然後我們寫單擊按鈕時的邏輯方法
// 單擊按鈕時打開或成片打開
private void open(MyButton btn) {
// 先将當期按鈕設定為不可見,即打開了按鈕
btn.setVisible(false);
// 判斷按鈕中 是否為數字還是空
switch (labels[btn.row][btn.col].getText()) {
// 如果是炸彈則将全部按鈕都打開,遊戲結束
case "*" :
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
buttons[i][j].setVisible(false);
}
}
break;
// 如果是空的則将他周圍空的按鈕都打開,進入遞歸
case "" :
for (int[] off: offset) {
int newRow = btn.row + off[0];
int newCol = btn.col + off[1];
if (verify(newRow, newCol)) {
MyButton sButton = buttons[newRow][newCol];
if (sButton.isVisible()) {
open(sButton);
}
}
}
default:
}
}
最後,我們在initButtons方法的單擊事件中引用這個方法
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
open((MyButton) e.getSource());
}});
大功告成,我們的簡易掃雷遊戲正式完成了!
總結
篇幅有限!篇幅有限!關于AVA完美之作掃雷完整版,就聊到這兒啦…啦…啦…
以上小編所介紹的全部相關的筆記資料都已整理成冊,不論是Redis面試+Redis實戰pdf,還是MongDB快速上手+MongDB叢集安全等手寫pdf筆記,想白嫖都很so easy!!
——如果你get到了,那就點個贊轉發支援一波吧!
——整理不易,白嫖私信我擷取資料,100%回複分享!
——也可以加小助手vx:xcw18874131605擷取資料哦
——祝前程似錦,offer不斷,好好學習,天天向上!