java翻牌源代码

package com.icss.java7_31;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.CompoundBorder;
import javax.swing.border.LineBorder;


public class RememberCard extends JFrame {

    //初始化游戏的行列数,行列数乘积必须为偶数
     
    private static final int ROWS = 4;
    private static final int COLUMNS = 4;
    private JTextField txt_Time;
    private boolean isRunning = false;
    
      //存放图片的目录,简单起见,存放图片的目录中图片个数为初始化的行列数乘积的一半
     
    private String picDir = "D:\\image";
    private String[] picture;
    protected boolean isStart;
    private PicPanel preOne = null;
    
    //用于标示已找到的对数
     
    private int count;
    private JPanel panel_Pic;

    public RememberCard() {
        setTitle("记忆纸牌");
        JPanel panel_Time = new JPanel();
        getContentPane().add(panel_Time, BorderLayout.NORTH);

        JLabel lbl_Time = new JLabel("用时");
        panel_Time.add(lbl_Time);

        txt_Time = new JTextField();
        txt_Time.setEditable(false);
        panel_Time.add(txt_Time);
        txt_Time.setColumns(10);

        JLabel lbl_Unit = new JLabel("秒");
        panel_Time.add(lbl_Unit);

        JButton btn_Start = new JButton("开始");
        panel_Time.add(btn_Start);
        panel_Pic = new JPanel();
        getContentPane().add(panel_Pic, BorderLayout.CENTER);
        btn_Start.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (isRunning) {
                    return;
                }
                setRunning(true);
                startGame();

            }
        });
        initPicPanels();
    }

    //初始化图片面板
     
    private void initPicPanels() {
        panel_Pic.setLayout(new GridLayout(ROWS, COLUMNS, 5, 5));
        initPictureIndex();
        //循环用于将文件夹里的图片加到面板上
        for (int i = 0; i < ROWS * COLUMNS; i++) {
            JPanel panel_1 = new PicPanel(this, picture[i]);
            panel_Pic.add(panel_1);
        }
    }

   //开始游戏
    protected void startGame() {
        new Thread() {
            @Override
            public void run() {
                long startTime = System.currentTimeMillis();//获取当前的时间
                while (count < ROWS * COLUMNS / 2) {
                    txt_Time.setText(((System.currentTimeMillis() - startTime)/1000 )
                            + "");//获取的时间为毫秒,所以/1000
                }
                JOptionPane.showMessageDialog(null,
                        "成功!共耗时" + txt_Time.getText() + "秒。");//通关提示语
                // 结束后重新初始化一下面板以便于下一次的运行
                count = 0;
                panel_Pic.removeAll();//清除面板上的图片
                initPicPanels();
                txt_Time.setText(null);
                panel_Pic.validate();
                isRunning = false;
            }
        }.start();
    }

    //初始化图片的索引并赋值每个图片的路径
    
    private void initPictureIndex() {
        picture = new String[ROWS * COLUMNS];
      
        File file = new File(picDir);
        File[] pics = file.listFiles();

        // 初始化一个ROWS*COLUMNS的int数组,里面存放每个图片的索引
        int[] indexs = getIndexs(picture.length, pics.length);
        for (int i = 0; i < indexs.length; i++) {
            picture[i] = pics[indexs[i]].getAbsolutePath();//将图片绝对路径的字符串存到picture数组中
        }
    }

    /* 根据提供的图片总数目(假设图片都是互不相同的)得到一个长度为sum的数组用来表示每个图片的索引
           sum的长度为游戏的行列数乘积
     */
    private int[] getIndexs(int sum, int picNums) {
        int half = sum / 2;

        if (picNums < half) {
            return getIndexsByMap(sum, picNums);
        }
        int[] tmpResult = new int[sum];
        Random random = new Random(System.currentTimeMillis());
        int temp = 0;
        LinkedList<Integer> list = new LinkedList<Integer>();
        while (list.size() != half) {
            temp = random.nextInt(picNums);
            if (!list.contains(temp)) {
                list.add(temp);
            } else if (picNums < half) {
                list.add(temp);
            }
        }

        for (int i = 0; i < tmpResult.length; i++) {
            tmpResult[i] = list.get(i >= half ? i % half : i);
        }
        // 将顺序打乱,否则会出现前半部分和后半部分是完全分开的情况
        LinkedList<Integer> _result = new LinkedList<Integer>();
        while (_result.size() != sum) {
            temp = random.nextInt(sum);
            if (!_result.contains(temp)) {
                _result.add(temp);
            }
        }
        int[] result = new int[sum];
        for (int i = 0; i < result.length; i++) {
            result[i] = tmpResult[_result.get(i)];
        }
        return result;
    }

 
    // 当图片数量小于总格子数一半时需要使用下面的方法获取,保证所有的图片都能使用上
    
    private int[] getIndexsByMap(int sum, int picNums) {
        int half = sum / 2;
        int[] tmpResult = new int[sum];
        Random random = new Random(System.currentTimeMillis());
        int temp = 0;
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        // 因为图片的数量小于sum的一半,因此先按顺序将图片索引都添加到map中以保证得到的结果中每个图片都被使用到
        for (int i = 0; i < picNums; i++) {
            map.put(i, 1);
        }
        int size = picNums;
        while (size != half) {
            temp = random.nextInt(picNums);
            if (!map.containsKey(temp)) {
                map.put(temp, 1);
            } else {
                map.put(temp, map.get(temp) + 1);
            }
            size++;
        }

        List<Integer> list = mapKeyToList(map);
        for (int i = 0; i < tmpResult.length; i++) {
            tmpResult[i] = list.get(i >= half ? i % half : i);
        }
        // 将顺序打乱,否则会出现前半部分和后半部分是完全分开的情况
        LinkedList<Integer> _result = new LinkedList<Integer>();
        while (_result.size() != sum) {
            temp = random.nextInt(sum);
            if (!_result.contains(temp)) {
                _result.add(temp);
            }
        }
        int[] result = new int[sum];
        for (int i = 0; i < result.length; i++) {
            result[i] = tmpResult[_result.get(i)];
        }
        return result;
    }

    /**
     * 将map中的key转换成一个list,其中每个key的value表示该key出现的次数,转换中如果次数多于1需要重复添加key到list中
     *
     * @param map
     * @return
     */
    private List<Integer> mapKeyToList(HashMap<Integer, Integer> map) {
        List<Integer> list = new ArrayList<Integer>();
        Iterator<Integer> keyIt = map.keySet().iterator();
        Integer key = 0;
        while (keyIt.hasNext()) {
            key = keyIt.next();
            if (map.get(key) == 1) {
                list.add(key);
            } else {
                for (int i = 0; i < map.get(key); i++) {
                    list.add(key);
                }
            }
        }
        return list;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                RememberCard remCard = new RememberCard();
                remCard.setSize(400, 300);
                remCard.setLocationRelativeTo(null);
                remCard.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                remCard.setVisible(true);
            }
        });
    }

    public PicPanel getPreOne() {
        return preOne;
    }

    public void setPreOne(PicPanel preOne) {
        this.preOne = preOne;
    }

    public void addCount() {
        count++;
    }

    public boolean isRunning() {
        return isRunning;
    }

    public void setRunning(boolean isRunning) {
        this.isRunning = isRunning;
    }
}

/**
 * @author jqs
 *
 *         图片面板,主要实现了图片的显示与图片相同判断
 */
class PicPanel extends JPanel {
    private static final long serialVersionUID = 2172162568449349737L;
    private String picPath;
    private JLabel lbl_Pic = new JLabel();
    private ImageIcon bgIcon = null;
    private boolean isShow = false;
    private RememberCard parent;
    private boolean finished = false;

    public PicPanel(RememberCard rememberCard, String picPath) {
        this.picPath = picPath;
        this.parent = rememberCard;
        this.setBorder(new CompoundBorder(null, new LineBorder(new Color(0, 0,
                0), 2)));
        this.setLayout(new BorderLayout());
        this.add(lbl_Pic, BorderLayout.CENTER);
        this.addMouseListener(mouseAdapter);
    }

    public String getPicPath() {
        return picPath;
    }

    public void setPicPath(String picPath) {
        this.picPath = picPath;
    }

    /**
     * 图片面板的鼠标事件监听,配对过程在此完成
     */
    private MouseAdapter mouseAdapter = new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
            new Thread() {
                public void run() {
                    if (!parent.isRunning() || finished) {
                        return;
                    }
                    isShow = !isShow;
                    if (isShow) {
                        if (bgIcon == null) {
                            initLabelImage();
                        }
                        PicPanel curOne = (PicPanel) lbl_Pic.getParent();
                        PicPanel preOne = parent.getPreOne();
                        if (preOne == null) {
                            parent.setPreOne(curOne);
                        } else {
                            boolean right = checkRight(curOne, preOne);
                            if (right) {
                                parent.setPreOne(null);
                                curOne.setFinished(true);
                                preOne.setFinished(true);
                                parent.addCount();
                            } else {
                                lbl_Pic.setIcon(bgIcon);
                                repaint();
                                try {
                                    Thread.sleep(50);
                                } catch (InterruptedException e1) {
                                    e1.printStackTrace();
                                }
                                lbl_Pic.setIcon(null);
                                isShow = !isShow;
                                repaint();
                                preOne.getMouseListeners()[0]
                                        .mouseClicked(null);
                                parent.setPreOne(null);
                                return;
                            }
                        }
                        lbl_Pic.setIcon(bgIcon);
                    } else {
                        lbl_Pic.setIcon(null);
                    }
                    repaint();

                };
            }.start();
        }

        /**
         * 检查两个面板显示的图片是否一致,根据图片的路径来判断,同时要保证两个面板不是同一个面板
         *
         * @param curOne
         * @param preOne
         * @return
         */
        private boolean checkRight(PicPanel curOne, PicPanel preOne) {
            return curOne.getPicPath().equals(preOne.getPicPath())
                    && !curOne.equals(preOne);
        }
    };

    /**
     * 初始化Label对象的image
     */
    private void initLabelImage() {
        try {
            Image image = ImageIO.read(new File(picPath));
            if (image != null) {
                int lblWidth = this.getWidth();
                int lblHeight = this.getHeight();
                bgIcon = new ImageIcon(image.getScaledInstance(lblWidth,
                        lblHeight, Image.SCALE_DEFAULT));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 当找到配对的图片面板后设置完成状态为true,此时点击图片面板已经无效了。
     *
     * @param b
     */
    protected void setFinished(boolean b) {
        finished = b;
    }
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值