Java版连连看

连连看大家应该都玩过,不多说直接上一个做好的界面截图吧,所有的功能都在上面的,要做的就只是如何去实现它们了。

差不多就是这个样子。先说一下大致的思路吧。首先编写基本的界面:把什么按钮啊,表格啊什么的都画上去。然后就是编写事件处理类,因为操作使用鼠标,所以加上鼠标监听。然后获取点击的坐标,根据坐标得出图片在数组中的位置。接着创建一个类,实现连连看消除的算法。这样就基本上可以开始游戏了。然后实现排行榜按钮和存档按钮的基本功能。最后加上一个线程类,用于处理倒计时。下面的介绍也基于这个顺序。

界面实现:这个其实没什么好说的,把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方法生成,不同的数字对应不同的图片。

连连看的算法:这里我使用的算法是比较容易理解和实现的分类算法,据说还有一种比较厉害的算法叫广度优先搜索,那个我不会,所以就只能用这种了。先说说连连看的规则吧,就是用不超过两次拐弯的直线能够相连就能够消除。这样分类算法就很好理解了,按照消除要拐弯的次数分为无折相连,一折相连和二折相连。首先是无折相连这个很好理解,要么他们左右相邻或者是上下相邻,要么就是同一行,两个方快中间没有阻隔或者是同一列中间没有阻隔。

就像上面的图,左边是不相邻的,右边是相邻的,这两种都属于无折的相连。然后是一折的相连。一折的相连就是拐一个弯,先看看示意图把:

其实无论是哪种情况,能够实现一折相连的方块都是在矩形的两个对顶角,所以只要判断矩形的另外两个对顶角是否能够实现无折相连就行了。最后是二折相连,同样是先看示意图:

二折的情况看似复杂,其实只要在水平方向上和垂直方向上分别进行遍历,如果是空格就判断这个空格是否能够和另一个格子一折相连就行了。其实整个算法有点像是递归,一折调用无折,二折调用一折。算法的思路大概就是这样。然后就上代码吧:

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,这样就能够遍历到了。不过在判断的时候要注意使用的是新数组的坐标还是旧数组的坐标(把新数组的坐标行下标和列下标都减一就是旧数组的行下标和列下标)。能够消除就意味着你的连连看游戏已经可以玩了,剩下的就是一些优化的问题了。

排行榜和存档功能的实现:这两个功能放一起讲,因为都用到了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();
            }
        }
    }

}

这样所有的东西也就都讲完了,剩下的就是如何把它们组织在一起形成你的东西了。

时间: 2024-10-09 08:02:56

Java版连连看的相关文章

排序算法Java版,以及各自的复杂度,以及由堆排序产生的top K问题

常用的排序算法包括: 冒泡排序:每次在无序队列里将相邻两个数依次进行比较,将小数调换到前面, 逐次比较,直至将最大的数移到最后.最将剩下的N-1个数继续比较,将次大数移至倒数第二.依此规律,直至比较结束.时间复杂度:O(n^2) 选择排序:每次在无序队列中"选择"出最大值,放到有序队列的最后,并从无序队列中去除该值(具体实现略有区别).时间复杂度:O(n^2) 直接插入排序:始终定义第一个元素为有序的,将元素逐个插入到有序排列之中,其特点是要不断的 移动数据,空出一个适当的位置,把待插

Java版贪吃蛇(比较完善的版本)

很认真的写的一个java版的贪吃蛇游戏,图形界面,支持菜单操作,键盘监听,可加速,减速,统计得分,设定运动速度,设定游戏背景颜色等!应该没有Bug了,因为全被我修改没了.哈哈. 下面是项目各包及类的层次关系: 游戏的主要运行界面截图如下: 下面是部分代码,详细源码见此链接:http://pan.baidu.com/s/1bnubnzh //Snake类: package com.huowolf.entities; import java.awt.Color; import java.awt.Gr

回溯算法解八皇后问题(java版)

八皇后问题是学习回溯算法时不得不提的一个问题,用回溯算法解决该问题逻辑比较简单. 下面用java版的回溯算法来解决八皇后问题. 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 思路是按行来规定皇后,第一行放第一个皇后,第二行放第二个,然后通过遍历所有列,来判断下一个皇后能否放在该列.直到所有皇后都放完,或者放哪

pureMVC java版搭建流程

转自:http://blog.csdn.net/sutaizi/article/details/6588004 pureMVC 是一个轻量级的框架 它在 flex中非常流行(和cairngorm差不多火) 目前几乎已经移植到所有平台上. 下面实现java版得pureMVC搭建 先给大家看总体的层次: 众所周知 pureMVC是一个轻量级的MVC框架 分为 Model ,View ,Controller.这三个是pureMVC的核心. 除此之外pureMVC中含有一个单例模式Facade.faca

AKKA文档(java版)

目前我正在翻译AKKA官网文档.翻译:吴京润 译者注:本人正在翻译AKKA官网文档,本篇是文档第一章,欢迎有兴趣的同学加入一起翻译.更多内容请读这里:https://tower.im/projects/ac49db18a6a24ae4b340a5fa22d930dc/lists/ded96c34f7ce4a6bb8b5473f596e1008/show/https://tower.im/projects/ac49db18a6a24ae4b340a5fa22d930dc/todos/640e53d

应用程序初次运行数据库配置小程序(Java版)

应用程序初始化数据库配置小程序 之前写过一个Java版的信息管理系统,但部署系统的时候还需要手动的去配置数据库和导入一些初始化的数据才能让系统运行起来,所以我在想是不是可以写一个小程序在系统初次运行的时候自动部署数据库和导入一些初始化数据.然后就有了以下的思路: 在应用程序入口处判断数据库是否已经配置完成,若配置完成则进入正常的登录系统完成正常操作即可,若未配置则进入数据库配置的小程序完成数据库配置然后再进入系统,但如何来判断是否已经配置完成呢,在这里我用的是比较原始的方法,配置数据库的时候系统

微博地址url(id)与mid的相互转换 Java版

原理: 新浪微博的URL都是如:http://weibo.com/2480531040/z8ElgBLeQ这样三部分. 第一部分(绿色部分)为新浪微博的域名,第二部分(红色部分)为博主Uid,第三部分(蓝色)为一串貌似随机的字符串. 如果通过方法能计算出蓝色字串与返回的数组里的对应关系则好解决多了. 首先分组蓝色字串 ,从后往前4个字符一组,得到以下三组字符:z8ElgBLeQ 将它们分别转换成62进制的数值则为 35, 2061702, 8999724  将它们组合起来就是一串 3520617

java版的QQ小程序

转载自:http://blog.csdn.net/lihongxun945/article/details/6114290 这是一个简单的java版的QQ小程序. 包括一个简单的服务器和一个简单的客户端. 运行时,先运行服务器,然后在运行客户端,就可以进行聊天了. 默认的配置是localhost,端口4545,更改ip就可以在两天电脑上进行聊天了. 目前不支持内网和外网之间的访问,也不支持多人聊天. 因为这只是一个简单的例子,感兴趣的同学可以通过改进,实现多人聊天和内外网之间的访问. 效果图:

青蛙的约会 java版

参考http://blog.csdn.net/polossk/article/details/9799735 package acm; public class FrogDate { public static void main(String[] args) { int x = 11,y = 21,m = 31,n = 41,l = 44; int ar=n-m,br=0,cr=x-y; int M = exGcd(n-m,l,ar,br); System.out.println("M:&qu