連連看你們應該都玩過,很少說直接上一個作好的界面截圖吧,全部的功能都在上面的,要作的就只是如何去實現它們了。java
差很少就是這個樣子。先說一下大體的思路吧。首先編寫基本的界面:把什麼按鈕啊,表格啊什麼的都畫上去。而後就是編寫事件處理類,由於操做使用鼠標,因此加上鼠標監聽。而後獲取點擊的座標,根據座標得出圖片在數組中的位置。接着建立一個類,實現連連看消除的算法。這樣就基本上能夠開始遊戲了。而後實現排行榜按鈕和存檔按鈕的基本功能。最後加上一個線程類,用於處理倒計時。下面的介紹也基於這個順序。c++
界面實現:這個其實沒什麼好說的,把JFrame的知識用上就行了。考慮到圖片的閃爍問題,在界面類中重寫paint方法,加上雙緩衝(雙緩衝不懂的,能夠自行百度或者看看我寫的Java版本2048)。因此就直接貼代碼了。算法
package com.cbs.look; public interface LookConfig { int x=50;//初始x座標,原來是10 int y=100;//初始y座標,原來是50 int space=10;//圖片間的間隔 int arc=50;//圓角矩形的弧度 int size=60;//圖片的大小 int num=9;//圖片類型 }
1 package com.cbs.look; 2 3 import java.awt.Color; 4 import java.awt.Font; 5 import java.awt.Graphics; 6 import java.awt.Graphics2D; 7 import java.awt.Image; 8 import java.awt.RenderingHints; 9 10 import javax.swing.ImageIcon; 11 import javax.swing.JButton; 12 import javax.swing.JFrame; 13 import javax.swing.JLabel; 14 import javax.swing.JOptionPane; 15 16 /** 17 * 連連看的主界面類 18 * 19 * @author CBS 20 * 21 */ 22 @SuppressWarnings("serial") 23 public class GameLook extends JFrame implements LookConfig { 24 25 private int[][] array = new int[8][8];// 數組用於保存界面的信息 26 27 JLabel timeJl;// 用於顯示剩餘時間 28 29 public static void main(String[] args) throws InterruptedException { 30 GameLook g = new GameLook(); 31 g.showUI(); 32 33 } 34 35 /** 36 * 初始化界面 37 * 38 * @throws InterruptedException 39 */ 40 public void showUI() throws InterruptedException { 41 setTitle("連連看"); 42 setSize(700, 800); 43 setDefaultCloseOperation(3); 44 setLocationRelativeTo(null); 45 setResizable(true); 46 setLayout(null); 47 48 // 添加新遊戲按鈕 49 // ImageIcon start = new ImageIcon("res/start.png"); 50 JButton startJB = new JButton("新遊戲"); 51 startJB.setBounds(30, 700, 100, 40); 52 // startJB.setBorderPainted(false);// 設置邊框爲空 53 startJB.setFocusable(false); 54 // startJB.setContentAreaFilled(false);// 設置內容空 55 this.add(startJB); 56 // 添加排行榜按鈕 57 JButton save = new JButton("排行榜"); 58 save.setFocusable(false); 59 save.setBounds(190, 700, 100, 40); 60 this.add(save); 61 62 // 添加存檔按鈕 63 JButton saveGame = new JButton("存檔"); 64 saveGame.setFocusable(false); 65 saveGame.setBounds(320, 700, 100, 40); 66 this.add(saveGame); 67 68 69 // 添加剩餘時間 70 JLabel jl = new JLabel("Time:"); 71 jl.setFont(new Font("", Font.BOLD, 20)); 72 jl.setBounds(440, 700, 80, 50); 73 this.add(jl); 74 75 // 顯示剩餘時間 76 timeJl = new JLabel("90"); 77 timeJl.setFont(new Font("", Font.BOLD, 20)); 78 timeJl.setBounds(520, 700, 80, 50); 79 this.add(timeJl); 80 81 setVisible(true); 82 83 GameListener gl = new GameListener(); 84 gl.setFrame(this); 85 gl.setTimeJl(timeJl); 86 gl.setArray(array); 87 saveGame.addActionListener(gl); 88 startJB.addActionListener(gl); 89 save.addActionListener(gl); 90 91 int i=JOptionPane.showConfirmDialog(this, "是否讀取上次的存檔", "讀檔", 92 JOptionPane.YES_NO_OPTION); 93 if(i==1){ 94 JOptionPane.showMessageDialog(this, "請按新遊戲開始遊戲吧!"); 95 }else{ 96 GameSave2 gs2=new GameSave2(); 97 CunD c=gs2.opean(); 98 if(c!=null){ 99 array=c.getArray(); 100 gl.setArray(array); 101 this.addMouseListener(gl); 102 this.repaint(); 103 TimeOut tt =new TimeOut(timeJl, this, gl); 104 gl.setTt(tt); 105 tt.setSeconds(c.getTime()); 106 tt.start(); 107 }else{ 108 JOptionPane.showMessageDialog(this, "讀取失敗!"); 109 } 110 } 111 112 113 } 114 115 @Override 116 public void paint(Graphics g) { 117 super.paint(g); 118 buffPaint(g); 119 } 120 121 /** 122 * 使用雙緩衝技術解決閃屏問題 123 * 124 * @param g傳入的畫筆對象 125 */ 126 public void buffPaint(Graphics g) { 127 Image i = createImage(space + (size + space) * array[0].length, space 128 + (size + space) * array.length); 129 Graphics2D g2d = (Graphics2D) i.getGraphics(); 130 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 131 RenderingHints.VALUE_ANTIALIAS_ON); 132 // 繪製背景矩形 133 g2d.setColor(new Color(210, 180, 140)); 134 g2d.fillRoundRect(0, 0, space + (size + space) * array[0].length, space 135 + (size + space) * array.length, arc, arc); 136 // 繪製背景方格 137 g2d.setColor(new Color(245, 245, 220)); 138 for (int r = 0; r < array.length; r++) { 139 for (int c = 0; c < array[r].length; c++) { 140 g2d.fillRect(space + (size + space) * c, space + (size + space) 141 * r, size, size); 142 } 143 } 144 // 繪製圖片 145 g2d.setColor(Color.BLUE); 146 g2d.setFont(new Font("宋體", Font.BOLD, 30)); 147 for (int r = 0; r < array.length; r++) { 148 for (int c = 0; c < array[r].length; c++) { 149 if (array[r][c] != 0) { 150 ImageIcon icon = new ImageIcon("res/" + array[r][c] 151 + ".jpg"); 152 Image image = icon.getImage(); 153 g2d.drawImage(image, space + (size + space) * c, space 154 + (size + space) * r, size, size, null); 155 } 156 } 157 } 158 g.drawImage(i, x, y, this); 159 } 160 }
事件處理類:鼠標的事件處理主要負責的是記錄兩次點擊的座標,而後判斷是否可以把兩個圖片消除,若是能夠消除圖片把對應的數組位置的數置爲0,而後重繪畫板,若是不行一樣重繪畫板消除選框及連線。動做的事件處理主要負責實現不一樣的按鈕的功能。數組
package com.cbs.look; import java.awt.BasicStroke; import java.awt.Color; import java.awt.FlowLayout; import java.awt.Font; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.List; import java.util.Random; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.plaf.FontUIResource; /** * 事件處理類 * @author CBS */ public class GameListener extends MouseAdapter implements LookConfig, ActionListener { // 用於控制座標的獲取 private boolean flag = true; private int r1, c1, r2, c2;// 對應數組的下標位置 private int x1, y1, x2, y2;// 鼠標點擊的座標 private int array[][];// 保存數組 private JFrame frame;// 用於獲取窗體對象,調用Repaint方法 private Graphics2D g;// 畫筆對象 JLabel timeJl;// 用於顯示剩餘時間 TimeOut tt ;// 倒計時線程類 private int x;// 保存畫框的頂點x座標 private int y;// 保存畫框的頂點y座標 public TimeOut getTt() { return tt; } public void setTt(TimeOut tt) { this.tt = tt; } public void setTimeJl(JLabel timeJl) { this.timeJl = timeJl; } public void setFrame(JFrame frame) { this.frame = frame; g = (Graphics2D) frame.getGraphics(); } public void setArray(int[][] array) { this.array = array; } @Override public void mousePressed(MouseEvent e) { // 獲取座標 if (flag) { x1 = e.getX() - 40; y1 = e.getY() - 50; flag = false; if (y1 / (size + space) - 1 >= array.length) r1 = array.length - 1; else if (y1 / (size + space) - 1 < 0) r1 = 0; else r1 = y1 / (size + space) - 1; if (x1 / (size + space) >= array[0].length) c1 = array[0].length - 1; else c1 = x1 / (size + space); g.setColor(Color.RED); g.setStroke(new BasicStroke(5)); x = space + space + c1 * (size + space) + 40; y = size + r1 * (size + space) + 50; g.drawRect(x, y, size, size); } else { x2 = e.getX() - 40; y2 = e.getY() - 50; flag = true; if (y2 / (size + space) - 1 >= array.length) r2 = array.length - 1; else if (y1 / (size + space) - 1 < 0) r1 = 0; else r2 = y2 / (size + space) - 1; if (x2 / (size + space) >= array[0].length) c2 = array[0].length - 1; else c2 = x2 / (size + space); g.setColor(Color.RED); g.setStroke(new BasicStroke(4)); x = space + space + c2 * (size + space) + 40; y = size + r2 * (size + space) + 50; g.drawRect(x, y, size, size); } GameUtil gu = new GameUtil(this.frame); if (array[r1][c1] == array[r2][c2] && flag && !(r1 == r2 && c2 == c1) && (array[r1][c1] != 0 || array[r2][c2] != 0)) { if (gu.wuZhe(r1, c1, r2, c2, array)) { array[r1][c1] = 0; array[r2][c2] = 0; g.setColor(Color.PINK); g.drawLine(2 * space + size / 2 + c2 * (size + space) + 40, size + size / 2 + r2 * (size + space) + 50, 2 * space + size / 2 + c1 * (size + space) + 40, size + size / 2 + r1 * (size + space) + 50); } else if (gu.yiZhe(r1, c1, r2, c2, array)) { array[r1][c1] = 0; array[r2][c2] = 0; g.setColor(Color.PINK); g.drawLine(2 * space + size / 2 + gu.getPath().get(0).y * (size + space) + 40, size + size / 2 + gu.getPath().get(0).x * (size + space) + 50, 2 * space + size / 2 + c1 * (size + space) + 40, size + size / 2 + r1 * (size + space) + 50); g.drawLine(2 * space + size / 2 + gu.getPath().get(0).y * (size + space) + 40, size + size / 2 + gu.getPath().get(0).x * (size + space) + 50, 2 * space + size / 2 + c2 * (size + space) + 40, size + size / 2 + r2 * (size + space) + 50); } else if (gu.erZhe(r1, c1, r2, c2, array)) { array[r1][c1] = 0; array[r2][c2] = 0; g.setColor(Color.PINK); g.drawLine(2 * space + size / 2 + gu.getPath().get(1).y * (size + space) + 40, size + size / 2 + gu.getPath().get(1).x * (size + space) + 50, 2 * space + size / 2 + c1 * (size + space) + 40, size + size / 2 + r1 * (size + space) + 50); // path的下標爲一的位置要減一,由於數組擴大了 g.drawLine(2 * space + size / 2 + (gu.getPath().get(0).y - 1) * (size + space) + 40, size + size / 2 + (gu.getPath().get(0).x - 1) * (size + space) + 50, 2 * space + size / 2 + gu.getPath().get(1).y * (size + space) + 40, size + size / 2 + gu.getPath().get(1).x * (size + space) + 50); g.drawLine(2 * space + size / 2 + (gu.getPath().get(0).y - 1) * (size + space) + 40, size + size / 2 + (gu.getPath().get(0).x - 1) * (size + space) + 50, 2 * space + size / 2 + c2 * (size + space) + 40, size + size / 2 + r2 * (size + space) + 50); } //實現消除控制重繪的刷新時間 Thread t=new Thread(); try { t.sleep(100); frame.repaint(); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } if (isWin(array)) { tt.setFlag(false); frame.removeMouseListener(this); JOptionPane.showMessageDialog(frame, "恭喜你," + "你贏了!!請點擊新遊戲開始新一局"); int i = JOptionPane.showConfirmDialog(frame, "是否記錄將你的信息記入排行榜", "排行榜", JOptionPane.YES_NO_OPTION); if (i == 0) { String str = JOptionPane.showInputDialog(frame, "請輸入你的名字", "排行榜", JOptionPane.YES_NO_OPTION); int time=90-tt.getSeconds(); User u = new User(str, time); GameSave gs = new GameSave(); gs.save(u); } } } //未實現消除,重繪去掉線條 if (flag) { Thread t=new Thread(); try { t.sleep(100); frame.repaint(); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } // 按鈕動做監聽 public void actionPerformed(ActionEvent e) { String str = e.getActionCommand(); if ("新遊戲".equals(str)) { for (int r = 0; r < array.length; r++) for (int c = 0; c < array[r].length; c++) if (array[r][c] != 0) { array[r][c] = 0; } if(tt!=null){ if(tt.isFlag()){ frame.removeMouseListener(this); tt.setFlag(false); } } randomData(); frame.repaint(); frame.addMouseListener(this); // 啓動線程 tt = new TimeOut(timeJl, frame, this); if(!tt.isFlag()) tt.setFlag(false); tt.start(); } if ("排行榜".equals(str)) { GameSave gs = new GameSave(); List<User> list = gs.opean(); for (int i = 0; i < list.size(); i++) { int flag = i; for (int j = i + 1; j < list.size(); j++) { if (list.get(i).getTime() > list.get(j).getTime()) flag = j; } if (flag != i) { User u1 = list.get(i); User u2 = list.get(flag); list.set(i, u2); list.set(flag, u1); } } JFrame jf = new JFrame(); jf.setTitle("排行榜"); jf.setDefaultCloseOperation(2); jf.setSize(300, 500); FlowLayout fl = new FlowLayout(FlowLayout.LEFT); jf.setLayout(fl); jf.setLocationRelativeTo(null); for (int i = 0; i < list.size(); i++) { JLabel jl = new JLabel(list.get(i).toString()); jl.setFont(new FontUIResource("楷體", Font.BOLD, 20)); jf.add(jl); } jf.setVisible(true); } if("存檔".equals(str)){ System.out.println(23333); GameSave2 gs2=new GameSave2(); int time=tt.getSeconds(); CunD c=new CunD(array, time); boolean is=gs2.save(c); if(is) JOptionPane.showMessageDialog(frame, "存檔成功!"); else JOptionPane.showMessageDialog(frame, "存檔失敗!"); } } /** * 生成隨機數字 */ public void randomData() { Random random = new Random(); int r1, r2, c1, c2; for (int i = 0; i < array.length * array[0].length / 2; i++) { do { r1 = random.nextInt(array.length); c1 = random.nextInt(array[r1].length); } while (array[r1][c1] != 0); array[r1][c1] = random.nextInt(num) + 1; do { r2 = random.nextInt(array.length); c2 = random.nextInt(array[r2].length); } while (array[r2][c2] != 0); array[r2][c2] = array[r1][c1]; } } //遍歷數組,判斷輸贏 public boolean isWin(int[][] array) { for (int r = 0; r < array.length; r++) for (int c = 0; c < array[r].length; c++) if (array[r][c] != 0) return false; return true; } }
這裏的圖片我使用的是直接繪製圖片,而不是經過按鈕,因此座標的判斷有些麻煩。數組的下標取得是經過鼠標座標整除方格的邊長加間隔,而後由數組下標取得屏幕座標則相反。初始數據是由randomData方法生成,不一樣的數字對應不一樣的圖片。dom
連連看的算法:這裏我使用的算法是比較容易理解和實現的分類算法,聽說還有一種比較厲害的算法叫廣度優先搜索,那個我不會,因此就只能用這種了。先說說連連看的規則吧,就是用不超過兩次拐彎的直線可以相連就可以消除。這樣分類算法就很好理解了,按照消除要拐彎的次數分爲無折相連,一折相連和二折相連。首先是無折相連這個很好理解,要麼他們左右相鄰或者是上下相鄰,要麼就是同一行,兩個方快中間沒有阻隔或者是同一列中間沒有阻隔。ide
就像上面的圖,左邊是不相鄰的,右邊是相鄰的,這兩種都屬於無折的相連。而後是一折的相連。一折的相連就是拐一個彎,先看看示意圖把:學習
其實不管是哪一種狀況,可以實現一折相連的方塊都是在矩形的兩個對頂角,因此只要判斷矩形的另外兩個對頂角是否可以實現無折相連就好了。最後是二折相連,一樣是先看示意圖:測試
二折的狀況看似複雜,其實只要在水平方向上和垂直方向上分別進行遍歷,若是是空格就判斷這個空格是否可以和另外一個格子一折相連就好了。其實整個算法有點像是遞歸,一折調用無折,二折調用一折。算法的思路大概就是這樣。而後就上代碼吧:優化
package com.cbs.look; import java.awt.Point; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; /** * 核心算法 * 判斷兩個方塊是否聯通 * @author CBS * */ public class GameUtil implements LookConfig { //path主要是記錄下相連的數組的位置,爲了方便實現連線的功能 private List<Point> path=new ArrayList<Point>(); public List<Point> getPath() { return path; } public GameUtil(JFrame frame) { } /** * 無折算法,無折的狀況,要麼同行,判斷列是否連通;要麼同列判斷行是否連通 * * @param r1第一個方塊行下標 * @param c1第一個方塊列下標 * @param r2第二個方塊行下標 * @param c2第二個方塊列下標 * @param array用於保存數組的信息 * @return 若是可以連通返回TRUE,or返回FALSE */ public boolean wuZhe(int r1, int c1, int r2, int c2, int[][] array) { if (r1 != r2 && c1 != c2) return false; // 若是兩點的x座標相等,則在水平方向上掃描 if (r1 == r2) { if (c1 == c2 - 1 || c2 == c1 - 1)// 列相鄰 return true; for (int i = Math.min(c1, c2) + 1; i < Math.max(c2, c1); i++) if (array[r1][i] != 0) return false; } // 若是兩點的y座標相等,則在豎直方向上掃描 else if (c1 == c2) { if (r1 == r2 - 1 || r2 == r1 - 1)// 行相鄰 return true; for (int i = Math.min(r1, r2) + 1; i < Math.max(r2, r1); i++) if (array[i][c1] != 0) return false; } return true; } /** * 一折算法,不管是哪一種狀況下,都只須要判斷對角的r1,c2和r2,c1和兩點是否連通 * * @param r1第一個方塊行下標 * @param c1第一個方塊列下標 * @param r2第二個方塊行下標 * @param c2第二個方塊列下標 * @param array 用於保存數組的信息 * @return 若是可以連通返回TRUE,or返回FALSE */ public boolean yiZhe(int r1, int c1, int r2, int c2, int[][] array) { // 若是屬於0折的狀況,直接返回FALSE if (r1 == r2 || c1 == c2) return false; // 測試對角點1 if (array[r1][c2] == 0) { boolean test1 = wuZhe(r1, c1, r1, c2, array); boolean test2 = test1 ? wuZhe(r1, c2, r2, c2, array) : test1; if (test1 && test2){ path.add(new Point(r1,c2)); return true; } } // 測試對角點2 if (array[r2][c1] == 0) { boolean test1 = wuZhe(r1, c1, r2, c1, array); boolean test2 = test1 ? wuZhe(r2, c1, r2, c2, array) : test1; if (test1 && test2){ path.add(new Point(r2,c1)); return true; } } return false; } /** * 二折算法 * * @param r1第一個方塊行下標 * @param c1第一個方塊列下標 * @param r2第二個方塊行下標 * @param c2第二個方塊列下標 * @param array用於保存數組的信息 * @return 若是可以連通返回TRUE,or返回FALSE */ public boolean erZhe(int r1, int c1, int r2, int c2, int[][] array) { //在原來數組的基礎上擴大一圈,用於判斷邊界的方格 int[][] newArray = new int[array.length + 2][array[0].length + 2]; for (int r = 0; r < array.length; r++) { for (int c = 0; c < array[r].length; c++) { newArray[r + 1][c + 1] = array[r][c]; } } //判斷是否二折鏈接 // 向下垂直遍歷 for (int i = r1 + 2; i < newArray.length; i++) { if (newArray[i][c1+1] == 0 ) { if(yiZhe(r2+1, c2+1, i, c1+1, newArray)){ path.add(new Point(i-1, c1)); return true; } }else break; } // 向上垂直遍歷 for (int i = r1 ; i > -1; i--) { if (newArray[i][c1+1] == 0 ){ if(yiZhe(i, c1+1, r2+1, c2+1, newArray)){ path.add(new Point(i-1, c1)); return true; } }else break; } // 向右水平遍歷 for (int i = c1 + 2; i < newArray[0].length; i++) { if (newArray[r1+1][i] == 0 ){ if( yiZhe(r2+1, c2+1, r1+1, i, newArray)){ path.add(new Point(r1,i-1)); return true; } }else break; } // 向左水平遍歷 for (int i = c1 ; i > -1; i--) { if (newArray[r1+1][i] == 0 ) { if(yiZhe(r1+1, i, r2+1, c2+1, newArray)){ path.add(new Point(r1,i-1)); return true; } }else break; } return false; } }
還有一個要說一下就是上面第一張圖的那種二折狀況,若是這種二折狀況處於數組的邊界的話,在使用上面的二折算法判斷就會由於數組的問題,永遠不可能實現相連。解決的方法就是:把數組擴大,在整個的數組外邊加上一層,也就是說原來4*4變成6*6。把全部除原來4*4以外的位置的值都設爲0,這樣就可以遍歷到了。不過在判斷的時候要注意使用的是新數組的座標仍是舊數組的座標(把新數組的座標行下標和列下標都減一就是舊數組的行下標和列下標)。可以消除就意味着你的連連看遊戲已經能夠玩了,剩下的就是一些優化的問題了。this
排行榜和存檔功能的實現:這兩個功能放一塊兒講,由於都用到了Java的IO的一些知識。這裏主要用到的是Java中的FileOutputStream和FileInputStream這兩個類。FileOutputStream這個類是把內存中的數據輸出到外部的存儲設備,主要的方法就是write(向目標文件一次寫入一個字節)和close(關閉輸出流);FileInputStream則是把外部的數據輸入到內存中供程序使用,主要的方法就是read(從目標文件一次讀取一個字節)和close(關閉輸入流)。存檔的思路就是:把當前的數組狀況和時間記錄下來(使用一個類來保存這兩個信息),保存到一個文件中,下次打開遊戲的時候詢問用戶是否載入進度。排行榜的話是若是玩家獲勝,就記錄下玩家的姓名和通關用時(一樣使用一個類),保存到文件中。下面是代碼,把存檔和排行榜的相關類都放進去了:
1 package com.cbs.look; 2 3 /** 4 * 存檔 5 * 6 * @author CBS 7 */ 8 9 public class CunD { 10 private int array[][]; 11 private int time; 12 13 public CunD() { 14 } 15 16 public CunD(int[][] array, int time) { 17 this.array = array; 18 this.time = time; 19 } 20 21 public int[][] getArray() { 22 return array; 23 } 24 25 public void setArray(int[][] array) { 26 this.array = array; 27 } 28 29 public int getTime() { 30 return time; 31 } 32 33 public void setTime(int time) { 34 this.time = time; 35 } 36 37 } 38 package com.cbs.look; 39 40 import java.io.FileInputStream; 41 import java.io.FileNotFoundException; 42 import java.io.FileOutputStream; 43 import java.io.IOException; 44 import java.io.InputStream; 45 import java.io.OutputStream; 46 47 /** 48 * 用於保存遊戲存檔的信息 49 * 50 * @author CBS 51 */ 52 public class GameSave2 { 53 54 public boolean save(CunD d) { 55 56 String path = "src/com/cbs/look/info.txt"; 57 58 try { 59 60 OutputStream os = new FileOutputStream(path); 61 os.write(d.getTime()); 62 for (int r = 0; r < d.getArray().length; r++) { 63 for (int c = 0; c < d.getArray()[0].length; c++) { 64 os.write(d.getArray()[r][c]); 65 } 66 } 67 os.close(); 68 return true; 69 } catch (FileNotFoundException e) { 70 e.printStackTrace(); 71 } catch (IOException e) { 72 e.printStackTrace(); 73 } 74 75 return false; 76 } 77 78 public CunD opean() { 79 String path = "src/com/cbs/look/info.txt"; 80 try { 81 InputStream is = new FileInputStream(path); 82 int time = is.read(); 83 int array[][]=new int[8][8]; 84 85 for (int i = 0; i < array.length; i++) 86 for (int j = 0; j < array[0].length; j++) 87 array[i][j] = is.read(); 88 CunD c=new CunD(array,time); 89 is.close(); 90 return c; 91 92 } catch (FileNotFoundException e) { 93 e.printStackTrace(); 94 } catch (IOException e) { 95 e.printStackTrace(); 96 } 97 return null; 98 } 99 } 100 package com.cbs.look; 101 102 /** 103 * 記錄排行榜的用戶信息的類 104 * 105 * @author CBS 106 * 107 */ 108 public class User { 109 110 private String name;//用戶名 111 112 private int time;//記錄用戶經過所用時間 113 114 public User() { 115 } 116 117 public User(String name, int time) { 118 this.name = name; 119 this.time = time; 120 } 121 122 public String getName() { 123 return name; 124 } 125 126 public void setName(String name) { 127 this.name = name; 128 } 129 130 public int getTime() { 131 return time; 132 } 133 134 public void setTime(int time) { 135 this.time = time; 136 } 137 138 @Override 139 public String toString() { 140 String str=name+"用時爲:"+time; 141 return str; 142 } 143 144 145 } 146 package com.cbs.look; 147 148 import java.io.DataInputStream; 149 import java.io.DataOutputStream; 150 import java.io.FileInputStream; 151 import java.io.FileNotFoundException; 152 import java.io.FileOutputStream; 153 import java.io.IOException; 154 import java.io.InputStream; 155 import java.io.OutputStream; 156 import java.util.ArrayList; 157 import java.util.List; 158 159 /** 160 * 用於保存遊戲排行榜信息 161 * 162 * @author CBS 163 */ 164 public class GameSave { 165 166 public boolean save(User user) { 167 168 String path = "src/com/cbs/look/save3.txt"; 169 170 try { 171 List<User> array = opean(); 172 if(array!=null){ 173 array.add(user); 174 for (int i=0;i<array.size()-1;i++) { 175 int flag=i; 176 for(int j=i+1;j<array.size();j++){ 177 if(array.get(i).getTime()>array.get(j).getTime()) 178 flag=j; 179 } 180 if(flag!=i){ 181 User u1=array.get(i); 182 User u2=array.get(flag); 183 array.set(i, u2); 184 array.set(flag, u1); 185 } 186 } 187 }else{ 188 array=new ArrayList<User>(); 189 array.add(user); 190 } 191 192 OutputStream os = new FileOutputStream(path); 193 DataOutputStream dos=new DataOutputStream(os); 194 //先寫入有幾條信息 195 os.write(array.size()); 196 for (int i = 0; i < array.size(); i++) { 197 User u = array.get(i); 198 dos.writeByte(u.getName().getBytes().length); 199 dos.write(u.getName().getBytes()); 200 dos.writeInt(u.getTime()); 201 } 202 os.close(); 203 dos.close(); 204 return true; 205 } catch (FileNotFoundException e) { 206 e.printStackTrace(); 207 } catch (IOException e) { 208 e.printStackTrace(); 209 } 210 211 return false; 212 } 213 214 public List<User> opean() { 215 String path = "src/com/cbs/look/save3.txt"; 216 try { 217 InputStream is = new FileInputStream(path); 218 DataInputStream dis = new DataInputStream(is); 219 220 //讀取有幾條信息 221 int size=is.read(); 222 List<User> list=new ArrayList<User>(); 223 224 if(size!=-1){ 225 for(int i=0;i<size;i++){ 226 byte bsize=dis.readByte(); 227 byte[] b=new byte[bsize]; 228 is.read(b); 229 int time=dis.readInt(); 230 User u=new User(new String(b),time); 231 list.add(u); 232 } 233 } 234 dis.close(); 235 is.close(); 236 return list; 237 238 } catch (FileNotFoundException e) { 239 e.printStackTrace(); 240 } catch (IOException e) { 241 e.printStackTrace(); 242 } 243 return null; 244 } 245 }
倒計時的實現:倒計時其實很簡單使用一個線程就好(若是線程不瞭解請自行百度或者學習,不用很瞭解,知道就行,只是爲了作個倒計時罷了),每次線程休眠一秒就讓時間減一,而後把時間在窗體中輸出就好了。也沒什麼可說的,上代碼咯:
package com.cbs.look; /** * 線程類,控制時間 */ import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; public class TimeOut extends Thread { private int seconds=90;//遊戲時間 private JFrame frame;//主窗體對象 private JLabel jl;//倒計時標籤 private boolean flag = true;// 控制線程結束 private GameListener gl;//事件處理類 // 在別的類中控制線程的關閉 public void setFlag(boolean flag) { this.flag = flag; } public boolean isFlag() { return flag; } public int getSeconds() { return seconds; } public void setSeconds(int seconds) { this.seconds = seconds; } public TimeOut(JLabel jl, JFrame frame, GameListener gl) { this.jl = jl; this.frame = frame; this.gl = gl; } @Override public void run() { // seconds = 90; jl.setText(seconds + ""); while (seconds-- > 0 && flag) { jl.setText(seconds + ""); if (seconds == 0) { JOptionPane.showMessageDialog(frame, "很差意思,時間用光了,請開始新遊戲"); frame.removeMouseListener(gl); } try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
這樣全部的東西也就都講完了,剩下的就是如何把它們組織在一塊兒造成你的東西了。