羊了个羊代码

Card类

/**
 * 卡牌
 * 继承 JButton,就是在JButton基础上进行扩展改造
 */
public class Card extends JButton {
    public Card(String name){
        //设置了大小
        setSize(59, 66);
        //设置不绘制边框
        setBorderPainted(false);
        //设置不填充内容区域,按钮是透明的!
        setContentAreaFilled(false);
        //设置按钮上的图片
        setIcon(new ImageIcon("images/"+name+".png"));
        //设置禁用时候的灰色图片
        setDisabledIcon(new ImageIcon("images/"+name+"2.png"));
        //设置按钮 的 名称 name
        setName(name);
    }

    @Override
    public String toString() {
        return getName();
    }

    /**
     * 判断当前牌是否盖上了 另外一张牌 card
     * @param card 另外一张牌
     * @return true 表示覆盖了,false 没有盖上
     */
    public boolean covered(Card card){
        int x1 = card.getX() - 59;
        int x2 = card.getX() + 59;
        int y1 = card.getY() - 66;
        int y2 = card.getY() + 66;
        return (getX() > x1 && getX() < x2) && (getY() > y1 && getY() < y2);
    }
    /**
     * 比较当前卡牌和另外一个卡牌是否”一样“ 名称一样
     * @param other 另外一张牌
     */
    public boolean sameAs(Card other){
        String name = getName();
        if (name == null){
            return false;
        }
        return name.equals(other.getName());
    }

    /**
     * 删除全部的鼠标点击事件
     */
    public void removeActionListeners(){
        ActionListener[] actionListeners = getActionListeners();
        for (ActionListener l:actionListeners){
            removeActionListener(l);
        }
    }
}
Yang类


public class Yang extends JFrame {
    /**
     * 窗口中内容面面板
     */
    private JPanel panel = new JPanel();
    /**
     * JLabel 是Swing中用于显示文字和图片的控件
     */
    private JLabel background;

    /**
     * 利用List集合保存全部的卡牌
     */
    private ArrayList<Card> cards = new ArrayList<>();

    /**
     * 利用List表示下方从槽子
     */
    private ArrayList<Card> though = new ArrayList<>();

    /**
     * 利用数组存储全部的 名称
     */
    private String[] names =   {"刷子","剪刀","叉子","奶瓶",
                                "干草","手套","树桩","棉花",
                                "毛线","水桶","火","玉米",
                                "白菜","草","萝卜","铃铛"};
    /**
     * 创建一个定时器,Java中提供单线程,定时计划
     */
    //private ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
    private Timer timer = new Timer();

    public Yang(){
        //设置窗口标题
        setTitle("羊了个羊");
        //设置窗口大小
        setSize(500, 850);
        //设置窗口不能被 拖大
        // setResizable(false);
        //设置窗口居中
        setLocationRelativeTo(null);
        //设置关闭窗口时候退出程序
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        //将内容面板添加到 窗口中
        add(panel);
        //关闭panel的布局管理器
        panel.setLayout(null);
        //加载图片
        background = new JLabel(new ImageIcon("images/背景.jpg"));
        //关闭布局以后,需要自定义元素位置才能显示
        background.setLocation(0,0);
        background.setSize(480,800);
        //显示图片
        panel.add(background);
        init(6);
    }
    /**
     * 创建全部卡牌,创建的牌放到集合 cards 中
     * @param times 是次数,需要是3的整数倍
     *              如 3 6 9 等
     */
    private void createCards(int times){
        for (int i=0; i<times; i++) {
            for (String name : names) {
                Card card = new Card(name);
                cards.add(card);
            }
        }
    }

    /**
     * 初始化游戏
     */
    private void init(int times){
        //利用 Card 简化代码
        createCards(times);//必须为的倍数,表示每张牌出现的次数
        //System.out.println(cards.size());
        //System.out.println(cards);
        //输出卡牌
        //printCards();
        //shuffle 洗牌,打乱
        Collections.shuffle(cards);
        // System.out.println(cards);
        //输出卡牌
        //printCards();
        //摆放牌到屏幕上
        deal(33,100,0,6, 7);
        deal(33+30,100+33,42,5, 6);
        deal(33, 100+66, 42+30, 4, 7);
        deal(33+30, 100+33, 42+30+28, 5, 6);
        deal(33,100+33,42+30+28+30,6,7);
        deal(33+30,100+66,42+30+28+30+42,5,6);
        checkCovered();
        //添加动作: 为每张牌添加鼠标点击事件。
        addAction();
    }

    /**
     * 为每个卡牌添加鼠标点击事件
     */
    private void addAction(){
        for (Card card:cards){
            //Card 从 JButton 继承了 添加鼠标事件方法。
            //ActionListener 是一个只有一个方法的功能性接口,可以利用lamdba进行实现
            card.addActionListener(e->{
                //System.out.println("点击卡牌");
                //事件来源就是被点击的牌, 称为被选定的牌对象
                Card selected = (Card) e.getSource();
                //System.out.println(selected);
                //使用方法处理点击事件: 卡牌进入槽子里
                cardToThough(selected);
            });
        }
    }

    private void cardToThough(Card selected) {
        //从原有集合中删除卡牌
        cards.remove(selected);
        //从 cards 中删除的牌,去除鼠标事件
        selected.removeActionListeners();
        //移动显示位置到槽子中
        //查找插入位置
        int found = -1;
        for (int i=0; i<though.size(); i++){
            Card card = though.get(i);
            if (card.sameAs(selected)){
                found = i;
                break;
            }
        }
        if (found == -1){
            //如果没有找到牌, 就插入到最后
            though.add(selected);
        }else{
            //如果找到了 牌, 就插入到找到的位置
            though.add(found, selected);
        }
        //删除重复的3张牌
        boolean flag = tryRemoveCards(found, selected);//判断是否删除了3张的卡牌
        //重新排列牌的显示位置
        int x = 22;
        for (Card card: though){
            card.setLocation(x, 642);
            x += 63;
        }
        panel.repaint();
        checkCovered();
        if (though.size() == 7 && flag == false){
            JOptionPane.showMessageDialog(this, "卡槽满了!");
            System.exit(0);
        }
        if (cards.size() == 0){
            //System.out.println("you win!!!");
            JOptionPane.showMessageDialog(this, "下一关!");
            //System.exit(0);
            init(9);
        }
    }

    private boolean tryRemoveCards(int found, Card selected) {
        boolean flag = false;
        //在最后时候追加时候,不需要删除牌
        if (found == -1){
            return flag;
        }
        //当前位置开始,到最后要至少有3张牌
        if (found + 3 <= though.size()){
            //检查当前牌和下下张牌是否一样
            Card nextNextCard = though.get(found+2);
            if (selected.sameAs(nextNextCard)){
                flag = true;
                timer.schedule(new TimerTask() {
                   @Override
                   public void run() {
                       //连续删除3张牌
                       Card c1 = though.remove(found);
                       Card c2 = though.remove(found);
                       Card c3 = though.remove(found);
                       //从界面上删除 卡牌
                       panel.remove(c1);
                       panel.remove(c2);
                       panel.remove(c3);
                       int x = 22;
                       for (Card card: though){
                           card.setLocation(x, 642);
                           x += 63;
                       }
                       panel.repaint();
                   }
                }, 200);
            }
        }
        return flag;
    }

    /**
     * 检查全都的牌相互遮挡关系
     */
    private void checkCovered(){
        //检查每个牌,是否被后续牌遮挡,如果遮挡就是 disable状态,否则是enable
        for (int i=0; i<cards.size(); i++){
            //找到当前牌
            Card card1 = cards.get(i);
            //检查后续牌是否遮盖了这张牌
            card1.setEnabled(true);
            for(int j=i+1; j<cards.size(); j++){
                Card card2 = cards.get(j);
                //检查后一张牌card2是否遮盖了牌card1
                if (card2.covered(card1)){
                    card1.setEnabled(false);
                }
            }
        }
    }

    private void printCards(){
        int i=1;
        for (Card card:cards){
            System.out.print(card + " ");
            if (i++ % 7 == 0){
                System.out.println();
            }
        }
        System.out.println();
        System.out.println();
    }

    /**
     * 摆放牌,摆放到没有牌就会自动结束
     * @param x 左上角的坐标x  x:33
     * @param y 左上角的坐标y  y:100
     * @param start 开始位置:0  42  42+30
     * @param rows 摆放行数  6
     * @param cols 摆放列数  7
     */
    private void deal(int x, int y, int start, int rows, int cols){
        //              循环到固定次数 并且还有可以使用的牌
        for (int i=0; i<rows * cols && i+start < cards.size(); i++){
            int x0 = x + i % cols * 59;
            int y0 = y + i / cols * 66;
            Card card = cards.get(i + start);
            card.setLocation(x0, y0);
            card.setEnabled(false);
            panel.add(card, 0);
        }
    }

    public static void main(String[] args) {
        Yang yang = new Yang();
        yang.setVisible(true);
    }
}

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值