swing 扫雷简单版实现代码-附注释

直接先上效果图

1.核心算法将扫雷看成是一个二维数组,每个格子分别用一个x,y来标识。如下图:

2.定义雷:我们需要生产10组随机(如0,4)这样的数据来表示一个雷。
3.当我们点击一个按钮时,拿到按钮的x,y值和我定义的10组随机数去比较,如果当前点击的按钮的x,y存在于我的随机数集合中,那么这个按钮即为雷

 

 好了不废话了直接上代码,代码中有详细的注释。

 

1.扫雷主程序入口

package com.yh;
/**
 * 扫雷主程序入口
 * 1.自定义一个jframe(SaoLeiFrame)窗体用来展示我们扫雷
 * 2.使用jframe默认布局
 * 3.向jframe放入一个jpanel(由于我们的jframe是borderLayout布局所以默认放在中部)
 * 4.创建一个自jpanel(SaoLeiPanel)设置为GirdLayout布局为10*10
 * 5.初始化(initPanel)我们的SaoLeiPanel
 * 6.initPanel中我们需要在每一个格子里面放一个button,我们通过嵌套for循环来放入
 *      外层循环表示行数,内层循环放入button
 * 7.创建我们自己button(SaoLeiBut),自定义int x,y这两个属性用来记录当前but
 *      在SaoLeiPanel网格布局中的位置
 * 8.在我们把but放入到SaoLeiPanel中时我们需要记录x,y的值,对应的是for中i和j
 * 9.我们需要在创建but时候对but进行一个鼠标点击事件的监听。为了方便我们点击but时对其进行处理
 * 10.创建一个事件类,我们这使SaoLeiPanel实现MouseListener。SaoLeiPanel来处理鼠标点击的事件
 * 11.创建我们的雷,由于我们的but都有一个xy来确定,所有我们只需要创建10组xy来表示我们的雷即可
 * 12.点击按钮进行处理,
 *         1.获取你点击的是哪个按钮。通过e.getComponent()方法来获取
 *         2.判断你是点击左键还右键。左键是打开按钮,右键标记按钮
 *             ①左键:拿到点击的按钮的xy值并与我的雷的集合进行比较,如果是雷,提示你踩雷了并游戏结束
 *             如果不是雷,以此but为中心,找到周边8个按钮,依次对8个按钮进行判断
 * */

public class SaoLeiMain {
    
    public static void main(String[] args) {
        SaoLeiFrame sf =  new SaoLeiFrame();
        sf.initFrame();
    }

}

 

2.扫雷Frame初始化

package com.yh;

import javax.swing.JFrame;
/**
 * 初始化面板
 * 
 * */
public class SaoLeiFrame extends JFrame {
    /**  */
    private static final long serialVersionUID = 583932182092822117L;
    public void initFrame(){
        SaoLeiPanel saoleipanel = new SaoLeiPanel(this);
        saoleipanel.initPanel();
        this.add(saoleipanel);
        
        this.setTitle("扫雷");
        this.setVisible(true);
        this.setSize(600, 600);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

3.扫雷的panel(核心)

package com.yh;

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JOptionPane;
import javax.swing.JPanel;


/***
 * 展示扫雷的按钮
 * 采用网格布局
 * 
 * */
public class SaoLeiPanel extends JPanel implements MouseListener{
    /**  */
    private static final long serialVersionUID = 61864807539421288L;
    
    //保存我们生成的雷
    List<String> booms =  new ArrayList<>();
    
    //保存我们所有按钮
    Map<String, SaoLeiBut> butsMap =  new HashMap<>();
    //将父窗口直接传过来方便我们操作
    SaoLeiFrame frame;
    
    public SaoLeiPanel(SaoLeiFrame frame){
        
        this.frame = frame;
    }
    
    
    //初始化panel
    public void initPanel(){
        this.setLayout(new GridLayout(10,10));
        //渲染格子
        for(int i = 0;i<10;i++){//循环格子的行数
            for(int j = 0;j<10;j++){//加入格子
                SaoLeiBut but =  new SaoLeiBut();
                but.addMouseListener(this);//添加鼠标事件
                but.setText(i+","+j);//设置每个格子展示内容
                but.x=i;//设置标识
                but.y=j;
                butsMap.put(i+","+j, but);//将产生的所有格子放入保存到map方便我们操作
                this.add(but);
                
            }
        }
        createBoom();//生成10组随机数来标识我们的雷
        
    }
    
    
    //生成雷
    public void createBoom(){
        //放雷
        List<String> bs =  new ArrayList<>();
        while(bs.size()<10){
            Double d1 = Math.random()*10;
            int x = d1.intValue();
            Double d2 = Math.random()*10;
            int y = d2.intValue();
            String boom = x+","+y;
            
            if(!bs.contains(boom)){//判断雷是否已存在
                System.out.println(boom);
                bs.add(boom);
            }
        }
        
        booms = bs;
        
    }


    @Override//鼠标点击
    public void mouseClicked(MouseEvent e) {
        SaoLeiBut slb = (SaoLeiBut)e.getComponent();//获取当前点击的按钮
        if(e.getModifiers() == 16){//如果是左键点击则打开我们的按钮
            String slbAdds = slb.x+","+slb.y;//获取当前点击的按钮标识
            
            if(booms.contains(slbAdds)){//踩雷提示
                JOptionPane.showMessageDialog(null, "哈哈哈 你踩雷!!!!!"); 
                frame.remove(this);//重置frame
                frame.initFrame();//重新初始化
                
            }else{//没有踩雷 这个时候我们需要判断我们周边的情况
                //打开自己及周边雷
                Map<String, Object> aroundMap  = getAround(slb);//获取周边格子的信息
                openButton(aroundMap,slb);//打开自己和周边
            }
        }else if(e.getModifiers() == 4){//如果是右键点击标记小红旗.这里我没有写
            System.out.println("鼠标点击右");
        }
        
    }
    
    @SuppressWarnings("unchecked")
    public void openButton(Map<String, Object> aroundMap,SaoLeiBut slb){
        int leicount = (int)aroundMap.get("i");//周边有没有雷
        
        List<String> arounds = (List<String>)aroundMap.get("arounds");//周边的按钮
        
        butsMap.put(slb.x+","+slb.y, null);
        
        
        
        if(leicount>0){//有雷 显示雷的数量
            slb.setText(leicount+"");
            slb.setBackground(Color.white);//设置背景为白色
            slb.removeMouseListener(this);//
        }else{//没有雷
            slb.setText("");//设置内容为空
            slb.setBackground(Color.white);//设置背景为白色
            slb.removeMouseListener(this);//取消监听
            
            
            //遍历  递归调用
            for(String key:butsMap.keySet() ){
                if(null!=butsMap.get(key)){
                    SaoLeiBut but =  butsMap.get(key);//转换成我们but
                    if(null!=arounds && arounds.contains(key)){//如果是当前点击的but的周边的but则记录
                        Map<String, Object> ms = getAround(but);//获取周边的雷的情况和周边按钮
                        openButton(ms,but);
                    }
                }
            }
        }
        
        
        
        
    }
    
    
    /**
     * 返回周边雷的数量及雷坐标
     * */
    public Map<String, Object> getAround(SaoLeiBut slb){
        int x = slb.x;//获取当前点击but的xy
        int y = slb.y;
        List<String> arounds =  new ArrayList<>();//定义一个集合用来存储周边but下标
        
        
        //获取周边but下标并保存至arounds
        if(y>0){
            String top = x+","+(y-1);//
            arounds.add(top);
        }
        if(y<9){
            String bottom  = x+","+(y+1);//
            arounds.add(bottom);
        }
        if(x>0){
            String left = (x-1)+","+y;//
            arounds.add(left);
        }
        if(x<9){
            String right = (x+1)+","+y;//
            arounds.add(right);
        }
        if(x>0&&y>0){
            String left_top = (x-1)+","+(y-1);//左上
            arounds.add(left_top);
        }
        if(x>0 && y<9){
            String left_bottom = (x-1)+","+(y+1);//左下
            arounds.add(left_bottom);
        }
        if(x<9&&y>0){
            String right_top = (x+1)+","+(y-1);//右上
            arounds.add(right_top);
        }
        if(x<9&&y<9){
            String right_bottom = (x+1)+","+(y+1);//右下
            arounds.add(right_bottom);
        }
        
        
        //判断周边的but是否是雷  用i来记录
        int i=0;
        for(String s:arounds){
            if(booms.contains(s)){
                i++;
            }
        }
        
        Map<String, Object> aroundMap =  new HashMap<>();
        
        
        aroundMap.put("i", i);
        aroundMap.put("arounds", arounds);
        return aroundMap;
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }


    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

}

 

1,自定义的button来表示我们每一个格子

package com.yh;

import javax.swing.JButton;
/**
 * 定义我们扫雷的按钮
 * 
 * */
public class SaoLeiBut  extends JButton{
    
    private static final long serialVersionUID = -8176636345385709660L;
    int x,y;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

package com.yh;/** * 扫雷主程序入口 * 1.自定义一个jframe(SaoLeiFrame)窗体用来展示我们扫雷 * 2.使用jframe默认布局 * 3.向jframe放入一个jpanel(由于我们的jframe是borderLayout布局所以默认放在中部) * 4.创建一个自jpanel(SaoLeiPanel)设置为GirdLayout布局为10*10 * 5.初始化(initPanel)我们的SaoLeiPanel * 6.initPanel中我们需要在每一个格子里面放一个button,我们通过嵌套for循环来放入 * 外层循环表示行数,内层循环放入button * 7.创建我们自己button(SaoLeiBut),自定义int x,y这两个属性用来记录当前but * 在SaoLeiPanel网格布局中的位置 * 8.在我们把but放入到SaoLeiPanel中时我们需要记录x,y的值,对应的是for中i和j * 9.我们需要在创建but时候对but进行一个鼠标点击事件的监听。为了方便我们点击but时对其进行处理 * 10.创建一个事件类,我们这使SaoLeiPanel实现MouseListener。SaoLeiPanel来处理鼠标点击的事件 * 11.创建我们的雷,由于我们的but都有一个xy来确定,所有我们只需要创建10组xy来表示我们的雷即可 * 12.点击按钮进行处理, * 1.获取你点击的是哪个按钮。通过e.getComponent()方法来获取 * 2.判断你是点击左键还右键。左键是打开按钮,右键标记按钮 * ①左键:拿到点击的按钮的xy值并与我的雷的集合进行比较,如果是雷,提示你踩雷了并游戏结束 * 如果不是雷,以此but为中心,找到周边8个按钮,依次对8个按钮进行判断 * */
public class SaoLeiMain {public static void main(String[] args) {SaoLeiFrame sf =  new SaoLeiFrame();sf.initFrame();}
}

 

posted @ 2019-04-26 15:49  典型的码农  阅读(446)  评论(0编辑  收藏  举报