java實現掃雷小遊戲
阿新 • • 發佈:2020-01-29
本文例項為大家分享了java實現掃雷小遊戲的具體程式碼,供大家參考,具體內容如下
程式碼:
package GUI; import java.util.Random; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.Font; import java.awt.Color; import java.awt.EventQueue; import java.awt.event.InputEvent; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JButton; import javax.swing.JTextField; import javax.swing.JMenuBar; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.UIManager; import javax.swing.ImageIcon; import javax.swing.BorderFactory; import javax.swing.border.EmptyBorder; public class MineSweeperFrame extends JFrame { // 遊戲模式編號 public static final int Custom_Mode = 0; public static final int Elementary_Mode = 1; public static final int Intermediate_Mode = 2; public static final int Advanced_Mode = 3; // 遊戲模式引數 public static final int[] Elementary = {9,9,10,Elementary_Mode}; public static final int[] Intermediate = {16,16,40,Intermediate_Mode}; public static final int[] Advanced = {16,30,99,Advanced_Mode}; // 遊戲字型、圖片、文字顏色 private static final Font FontC = new Font("Consolas",Font.PLAIN,22); private static final Font FontD = new Font("等線",20); private static final ImageIcon imgicon = new ImageIcon( MineSweeperFrame.class.getResource("/Images/icon.jpg")); private static final ImageIcon imgflag = new ImageIcon( MineSweeperFrame.class.getResource("/Images/flag.png")); private static final ImageIcon imgbomb = new ImageIcon( MineSweeperFrame.class.getResource("/Images/bomb.png")); private static final Color[] NumberColor = {Color.blue,Color.green,Color.orange,Color.magenta,Color.red,Color.cyan,Color.black,Color.gray}; // 資料檔案及高分記錄 private static File file = new File("MineSweeper.txt"); private static int HighScore_Elementary; private static int HighScore_Intermediate; private static int HighScore_Advanced; private int gamemode; private int row; private int column; private int area; private int minecount; private int flagcount; private int enablecount; private boolean[][] minearea; private boolean[][] flagmark; private boolean isGameOver; private boolean isFirstClick; private TimeThread timeThread; private JPanel contentPane; private JMenuBar menuBar; private JPanel pnlCount; private JPanel pnlMine; private MineButton[][] btnMine; private JTextField txtTime; private JTextField txtCount; /** * Launch the application. */ public static void main(String[] args) { int[] i = getDataFromFile(); EventQueue.invokeLater(new Runnable() { public void run() { try { new MineSweeperFrame(i[0],i[1],i[2],i[3]); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the frame. */ public MineSweeperFrame(int row,int column,int minecount,int mode) { // 設定各元件的預設字型 UIManager.put("Menu.font",FontD); UIManager.put("Label.font",FontD); UIManager.put("Button.font",FontD); UIManager.put("MenuBar.font",FontD); UIManager.put("MenuItem.font",FontD); UIManager.put("TextField.font",FontD); UIManager.put("OptionPane.buttonFont",FontD); UIManager.put("OptionPane.messageFont",FontD); setTitle("掃雷"); setResizable(false); // 設定視窗不可改變大小 setVisible(true); // 設定視窗初始可見 setIconImage(imgicon.getImage()); // 設定窗體的icon setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 註冊監聽器,響應視窗關閉事件 addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e){ saveDataToFile(); } }); menuBar = new JMenuBar(); setJMenuBar(menuBar); JMenu mGame = new JMenu("遊戲"); menuBar.add(mGame); JMenu mRestart = new JMenu("重新開始"); mGame.add(mRestart); JMenuItem mitRestart = new JMenuItem("重新開始本局"); mitRestart.addActionListener(new RestartListener()); mRestart.add(mitRestart); JMenuItem mitReset = new JMenuItem("開始新的遊戲"); mitReset.addActionListener(new ResetMineListener()); mRestart.add(mitReset); JMenu mDifficulty = new JMenu("難度設定"); mGame.add(mDifficulty); JMenuItem mitElementary = new JMenuItem("初級"); mitElementary.addActionListener(new ResetModeListener(Elementary)); mDifficulty.add(mitElementary); JMenuItem mitIntermediate = new JMenuItem("中級"); mitIntermediate.addActionListener(new ResetModeListener(Intermediate)); mDifficulty.add(mitIntermediate); JMenuItem mitAdvanced = new JMenuItem("高階"); mitAdvanced.addActionListener(new ResetModeListener(Advanced)); mDifficulty.add(mitAdvanced); JMenuItem mitCustom = new JMenuItem("自定義"); mitCustom.addActionListener(new CustomSizeFrameListener()); mDifficulty.add(mitCustom); JMenuItem mitHighScore = new JMenuItem("高分榜"); mitHighScore.addActionListener(new HighScoreListener()); mGame.add(mitHighScore); mGame.addSeparator(); JMenuItem mitExit = new JMenuItem("退出"); // 註冊監聽器,監聽“退出”選單項 mitExit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { saveDataToFile(); System.exit(0); } }); mGame.add(mitExit); JMenu mHelp = new JMenu("幫助"); mHelp.add(new JMenuItem("http://www.baidu.com/")); menuBar.add(mHelp); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(10,10)); contentPane.setLayout(new BorderLayout(0,0)); setContentPane(contentPane); pnlCount = new JPanel(); contentPane.add(pnlCount,BorderLayout.NORTH); JLabel lblTime = new JLabel("時間"); pnlCount.add(lblTime); txtTime = new JTextField("0",3); txtTime.setEditable(false); pnlCount.add(txtTime); JLabel lblCount = new JLabel("計數"); pnlCount.add(lblCount); txtCount = new JTextField("0/" + minecount,5); txtCount.setEditable(false); pnlCount.add(txtCount); pnlMine = new JPanel(); contentPane.add(pnlMine,BorderLayout.CENTER); gamemode = mode; setMineArea(row,column,minecount); setMinePosition(); setMineButton(); UIManager.put("Label.font",FontC); } // 從檔案中讀取資料 public static int[] getDataFromFile() { try { FileInputStream fis = new FileInputStream(file); byte[] buffer = new byte[256]; int size = fis.read(buffer); fis.close(); String[] s = new String(buffer,size).split(" "); HighScore_Elementary = Integer.parseInt(s[0]); HighScore_Intermediate = Integer.parseInt(s[1]); HighScore_Advanced = Integer.parseInt(s[2]); int[] i = {Integer.parseInt(s[3]),Integer.parseInt(s[4]),Integer.parseInt(s[5]),Integer.parseInt(s[6])}; return i; } catch (Exception e) { HighScore_Elementary = Integer.MAX_VALUE; HighScore_Intermediate = Integer.MAX_VALUE; HighScore_Advanced = Integer.MAX_VALUE; return Elementary; } } // 儲存資料到檔案 public void saveDataToFile() { try { String s = HighScore_Elementary + " " + HighScore_Intermediate + " " + HighScore_Advanced + " " + row + " " + column + " " + minecount + " " + gamemode; FileOutputStream fos = new FileOutputStream(file); fos.write(s.getBytes()); fos.close(); } catch (IOException e) { e.printStackTrace(); } } // 初始化面板的各項引數 private void setMineArea(int row,int minecount) { setSize(30 * column + 20,30 * row + 120); // 設定視窗在螢幕的正中心 setLocationRelativeTo(null); this.row = row; this.column = column; this.minecount = minecount; area = row * column; flagcount = 0; enablecount = area; minearea = new boolean[row][column]; flagmark = new boolean[row][column]; isGameOver = false; isFirstClick = true; } // 隨機生成地雷的位置 private void setMinePosition(){ // 生成minecount個不重複的隨機數 int[] pos = new int[area]; for (int i = 0; i < area; i++) { pos[i] = i; } Random rand = new Random(); for (int i = 0; i < minecount; i++) { int n = rand.nextInt(area - i); minearea[pos[n] / column][pos[n] % column] = true; pos[n] = pos[area - i - 1]; } } // 向地雷面板上新增按鈕 private void setMineButton() { pnlMine.setLayout(new GridLayout(row,column)); btnMine = new MineButton[row][column]; for (int i = 0; i < row; i++) { for (int j = 0; j < column; j++) { btnMine[i][j] = new MineButton(i,j); pnlMine.add(btnMine[i][j]); } } } // “重新開始本局”選單項監聽類 private class RestartListener implements ActionListener { public void actionPerformed(ActionEvent e) { new MenuFunction().Restart(); } } // “開始新的的遊戲”選單項監聽類 private class ResetMineListener implements ActionListener { public void actionPerformed(ActionEvent e) { new MenuFunction().ResetMine(); } } // “遊戲模式設定”選單項監聽類 private class ResetModeListener implements ActionListener { private int[] mode; public ResetModeListener(int[] mode) { this.mode = mode; } public void actionPerformed(ActionEvent e) { if (gamemode == mode[3]) { new MenuFunction().ResetMine(); } else { new MenuFunction().ResetSize(mode[0],mode[1],mode[2]); gamemode = mode[3]; } } } // “自定義”選單項監聽類,JFrame視窗的子類 private class CustomSizeFrameListener extends JFrame implements ActionListener { public CustomSizeFrameListener() { setTitle("自定義"); setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); setSize(320,220); setLocationRelativeTo(null); // 設定視窗在螢幕的正中心 setResizable(false); // 設定窗體不可改變大小 JPanel contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5,5,5)); contentPane.setLayout(new GridLayout(4,0)); setContentPane(contentPane); JPanel pnlRow = new JPanel(); contentPane.add(pnlRow); pnlRow.add(new JLabel("行數:")); JTextField txtRow = new JTextField(10); pnlRow.add(txtRow); JPanel pnlColumn = new JPanel(); contentPane.add(pnlColumn); pnlColumn.add(new JLabel("列數:")); JTextField txtColumn = new JTextField(10); pnlColumn.add(txtColumn); JPanel pnlMineCount = new JPanel(); contentPane.add(pnlMineCount); pnlMineCount.add(new JLabel("雷數:")); JTextField txtMineCount = new JTextField(10); pnlMineCount.add(txtMineCount); JPanel pnlButton = new JPanel(); contentPane.add(pnlButton); JButton btnOK = new JButton("確定"); btnOK.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { int r = Integer.parseInt(txtRow.getText().trim()); int c = Integer.parseInt(txtColumn.getText().trim()); int count = Integer.parseInt(txtMineCount.getText().trim()); if (r <= 0 || c <= 0 || r > 24 || c > 30) { JOptionPane.showMessageDialog(null,"限制行數:1~24\n限制列數:1~30","警告",JOptionPane.WARNING_MESSAGE); return; } if (count <= 0 || count > r * c) { JOptionPane.showMessageDialog(null,"限制雷數:1~" + (r * c),JOptionPane.WARNING_MESSAGE); return; } new MenuFunction().ResetSize(r,c,count); gamemode = Custom_Mode; setVisible(false); } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(null,"無效輸入!","錯誤",JOptionPane.ERROR_MESSAGE); } } }); pnlButton.add(btnOK); } public void actionPerformed(ActionEvent e) { setVisible(true); } } // “高分榜”選單項監聽類 private class HighScoreListener implements ActionListener { public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(null,"初級:" + HighScore_Elementary + "秒\n中級:" + HighScore_Intermediate + "秒\n高階:" + HighScore_Advanced + "秒","高分榜",JOptionPane.INFORMATION_MESSAGE); } } // 選單欄事件監聽函式類 private class MenuFunction { // “重新開始本局”函式 public void Restart() { flagcount = 0; enablecount = area; if (!isFirstClick) { timeThread.interrupt(); isFirstClick = true; txtTime.setText("0"); } txtCount.setText("0/" + minecount); for (int i = 0; i < row; i++) { for (int j = 0; j < column; j++) { flagmark[i][j] = false; btnMine[i][j].removeLabel(); btnMine[i][j].setIcon(null); btnMine[i][j].setOriginalStyle(); btnMine[i][j].setEnabled(true); } } if (isGameOver) { for (int i = 0; i < row; i++) { for (int j = 0; j < column; j++) { btnMine[i][j].setMineListener(); } } isGameOver = false; } } // “開始新的遊戲”函式 public void ResetMine() { minearea = new boolean[row][column]; setMinePosition(); Restart(); } // “遊戲模式設定”函式 public void ResetSize(int r,int c,int count) { Restart(); txtCount.setText("0/" + count); pnlMine.removeAll(); setMineArea(r,count); setMinePosition(); setMineButton(); } } // 地雷區按鈕監聽類 private class MineListener extends MouseAdapter { private int r; private int c; private boolean bothpress; private MouseFunction mousefunction; public MineListener(int r,int c) { this.r = r; this.c = c; mousefunction = new MouseFunction(r,c); } // 滑鼠點選時觸發 public void mousePressed(MouseEvent e) { // 判斷是否為左右雙鍵同時點選 int d = e.getModifiersEx(); if (d == InputEvent.BUTTON1_DOWN_MASK + InputEvent.BUTTON3_DOWN_MASK) { bothpress = true; } else { bothpress = false; } if (bothpress) { mousefunction.bothPressed(); } } // 滑鼠釋放時觸發 public void mouseReleased(MouseEvent e) { if (bothpress) { mousefunction.bothReleased(); } else if (e.getButton() == MouseEvent.BUTTON1) { mousefunction.leftReleased(r,c); } else if (e.getButton() == MouseEvent.BUTTON3 && !bothpress) { mousefunction.rightReleased(); } if (minecount == enablecount) { mousefunction.Success(); } } } // 地雷區滑鼠點選事件監聽函式類 private class MouseFunction { private int r; private int c; private boolean[] bool; public MouseFunction(int r,int c) { this.r = r; this.c = c; bool = surroundingButtons(r,c); } // 判斷被點選按鈕周邊3*3範圍內有無其它按鈕 private boolean[] surroundingButtons(int r,int c) { boolean[] bool = {true,true,true}; if (r == 0) {bool[0] = bool[1] = bool[2] = false;} if (r == row - 1) {bool[6] = bool[7] = bool[8] = false;} if (c == 0) {bool[0] = bool[3] = bool[6] = false;} if (c == column - 1) {bool[2] = bool[5] = bool[8] = false;} return bool; } // 左鍵釋放函式 public void leftReleased(int r,int c) { if (isFirstClick) { timeThread = new TimeThread(); timeThread.start(); isFirstClick = false; } if (flagmark[r][c] || !btnMine[r][c].isEnabled()) {return;} if (minearea[r][c]) {GameOver(r,c); return;} boolean[] bool = surroundingButtons(r,c); int i = 0; if (bool[0] && minearea[r - 1][c - 1]) {i++;} if (bool[1] && minearea[r - 1][c]) {i++;} if (bool[2] && minearea[r - 1][c + 1]) {i++;} if (bool[3] && minearea[r][c - 1]) {i++;} if (bool[5] && minearea[r][c + 1]) {i++;} if (bool[6] && minearea[r + 1][c - 1]) {i++;} if (bool[7] && minearea[r + 1][c]) {i++;} if (bool[8] && minearea[r + 1][c + 1]) {i++;} btnMine[r][c].setDisabledStyle(); btnMine[r][c].setEnabled(false); enablecount--; if (i != 0) { btnMine[r][c].setLabel(i); } else { if (bool[0]) {leftReleased(r - 1,c - 1);} if (bool[1]) {leftReleased(r - 1,c);} if (bool[2]) {leftReleased(r - 1,c + 1);} if (bool[3]) {leftReleased(r,c - 1);} if (bool[5]) {leftReleased(r,c + 1);} if (bool[6]) {leftReleased(r + 1,c - 1);} if (bool[7]) {leftReleased(r + 1,c);} if (bool[8]) {leftReleased(r + 1,c + 1);} } } // 右鍵釋放函式 public void rightReleased() { if (flagmark[r][c]) { btnMine[r][c].setIcon(null); flagmark[r][c] = false; flagcount--; txtCount.setText(flagcount + "/" + minecount); } else { if (btnMine[r][c].isEnabled()) { btnMine[r][c].setIcon(imgflag); flagmark[r][c] = true; flagcount++; txtCount.setText(flagcount + "/" + minecount); } } } // 雙鍵點選函式 public void bothPressed() { if (flagmark[r][c]) {return;} int k = 0; for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (bool[k++] && btnMine[r + i][c + j].isEnabled() && !flagmark[r + i][c + j]) { btnMine[r + i][c + j].setClickedStyle(); } } } } // 雙鍵釋放函式 public void bothReleased() { if (flagmark[r][c]) {return;} int k = 0,m = 0,n = 0; for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (bool[k++]) { if (btnMine[r + i][c + j].isEnabled() && !flagmark[r + i][c + j]) { btnMine[r + i][c + j].setOriginalStyle(); } if (minearea[r + i][c + j]) { m++; } if (flagmark[r + i][c + j]) { n++; } } } } if (btnMine[r][c].isEnabled()) {return;} if (m == n) { if (bool[0] && !flagmark[r - 1][c - 1]) {leftReleased(r - 1,c - 1);} if (bool[1] && !flagmark[r - 1][c]) {leftReleased(r - 1,c);} if (bool[2] && !flagmark[r - 1][c + 1]) {leftReleased(r - 1,c + 1);} if (bool[3] && !flagmark[r][c - 1]) {leftReleased(r,c - 1);} if (bool[5] && !flagmark[r][c + 1]) {leftReleased(r,c + 1);} if (bool[6] && !flagmark[r + 1][c - 1]) {leftReleased(r + 1,c - 1);} if (bool[7] && !flagmark[r + 1][c]) {leftReleased(r + 1,c);} if (bool[8] && !flagmark[r + 1][c + 1]) {leftReleased(r + 1,c + 1);} } } // 遊戲結束函式 public void GameOver(int r,int c) { btnMine[r][c].setBackground(Color.red); for (int i = 0; i < row; i++) { for (int j = 0; j < column; j++) { if (minearea[i][j]) { btnMine[i][j].setIcon(imgbomb); } btnMine[i][j].removeMineListener(); } } timeThread.interrupt(); JOptionPane.showMessageDialog(null,"Game Over","提示",JOptionPane.INFORMATION_MESSAGE); isGameOver = true; } // 遊戲勝利函式 public void Success() { txtCount.setText(minecount + "/" + minecount); for (int i = 0; i < row; i++) { for (int j = 0; j < column; j++) { if (minearea[i][j]) { btnMine[i][j].setIcon(imgflag); } btnMine[i][j].removeMineListener(); } } if (timeThread != null) { timeThread.interrupt(); } String s = "You Win!"; int time = Integer.parseInt(txtTime.getText()); switch (gamemode) { case Elementary_Mode: if (time < HighScore_Elementary) { HighScore_Elementary = time; s = "New Record!"; } break; case Intermediate_Mode: if (time < HighScore_Intermediate) { HighScore_Intermediate = time; s = "New Record!"; } break; case Advanced_Mode: if (time < HighScore_Advanced) { HighScore_Advanced = time; s = "New Record!"; } } JOptionPane.showMessageDialog(null,s + "\n用時:" + time + "秒",JOptionPane.INFORMATION_MESSAGE); isGameOver = true; } } // 地雷區按鈕類,JButton按鈕的子類 private class MineButton extends JButton { private MineListener mineListener; private JLabel lbl; private MineButton() { super(null,null); setBackground(Color.lightGray); // 設定凸起來的按鈕 setBorder(BorderFactory.createRaisedBevelBorder()); } public MineButton(int r,int c) { this(); mineListener = new MineListener(r,c); addMouseListener(mineListener); } public void setMineListener() { addMouseListener(mineListener); } public void removeMineListener() { removeMouseListener(mineListener); } public void setOriginalStyle() { setBackground(Color.lightGray); // 設定凸起來的按鈕 setBorder(BorderFactory.createRaisedBevelBorder()); } public void setDisabledStyle() { setBackground(null); // 設定按鈕邊框線條 setBorder(BorderFactory.createLineBorder(Color.lightGray)); } public void setClickedStyle() { setBackground(Color.lightGray); // 設定凹下去的按鈕 setBorder(BorderFactory.createLoweredBevelBorder()); } public void setLabel(int i) { lbl = new JLabel(String.valueOf(i)); lbl.setHorizontalAlignment(JLabel.CENTER); lbl.setVerticalAlignment(JLabel.CENTER); lbl.setForeground(NumberColor[i - 1]); setLayout(new BorderLayout(0,0)); add(lbl,BorderLayout.CENTER); } public void removeLabel() { if (lbl != null) { remove(lbl); lbl = null; } } } // 執行緒類,遊戲開始後每隔一秒重新整理txtTime文字框裡顯示的時間 private class TimeThread extends Thread { // 重寫run()方法 public void run() { // 獲取當前系統時間 long startTime = System.currentTimeMillis(); // 非阻塞過程中通過判斷中斷標誌來退出 while (!isInterrupted()) { // 獲取當前的系統時間,與初始時間相減就是程式執行的毫秒數,除以1000就是秒數 long endTime = System.currentTimeMillis(); long usedTime = (endTime - startTime) / 1000; txtTime.setText(String.valueOf(usedTime)); try { // 執行緒掛起一秒鐘 Thread.sleep(1000); // 阻塞過程捕獲中斷異常來退出 } catch (InterruptedException e) { e.printStackTrace(); // 捕獲到異常之後,執行break跳出迴圈 break; } } } } }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。