Java版連連看

連連看你們應該都玩過,很少說直接上一個作好的界面截圖吧,全部的功能都在上面的,要作的就只是如何去實現它們了。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;//圖片類型
}
View Code
  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 }
View Code

事件處理類:鼠標的事件處理主要負責的是記錄兩次點擊的座標,而後判斷是否可以把兩個圖片消除,若是能夠消除圖片把對應的數組位置的數置爲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;
    }
}
View Code

這裏的圖片我使用的是直接繪製圖片,而不是經過按鈕,因此座標的判斷有些麻煩。數組的下標取得是經過鼠標座標整除方格的邊長加間隔,而後由數組下標取得屏幕座標則相反。初始數據是由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;
        
    }

}
View Code

還有一個要說一下就是上面第一張圖的那種二折狀況,若是這種二折狀況處於數組的邊界的話,在使用上面的二折算法判斷就會由於數組的問題,永遠不可能實現相連。解決的方法就是:把數組擴大,在整個的數組外邊加上一層,也就是說原來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 }
View Code

倒計時的實現:倒計時其實很簡單使用一個線程就好(若是線程不瞭解請自行百度或者學習,不用很瞭解,知道就行,只是爲了作個倒計時罷了),每次線程休眠一秒就讓時間減一,而後把時間在窗體中輸出就好了。也沒什麼可說的,上代碼咯:

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();
            }
        }
    }

}
View Code

這樣全部的東西也就都講完了,剩下的就是如何把它們組織在一塊兒造成你的東西了。

相關文章
相關標籤/搜索