[Java] 游戏--扫雷 →→→→→进入此内容的聊天室

来自 , 2020-09-16, 写在 Java, 查看 134 次.
URL http://www.code666.cn/view/996009f2
  1. 1.主类
  2. package s1213扫雷6;
  3. //3.改变难度  关闭旧窗体,新建一个窗体,执行所有原来的代码
  4. //7.菜单栏选项的时间,应该放在public void actionPerformed(ActionEvent e) 这个方法里面
  5. //8尽量使用if+elseif 少用if+else 因为一旦情况发生改变,else很容易出现判断失误的情况
  6. //10.每一次更改状态变量都要写上条件,因为以后更改程序,有可能发生条件变化,原代码就会出错!!!
  7. //12.打开和读取文件的功能
  8. import javax.swing.ImageIcon;
  9. import javax.swing.JFileChooser;
  10. import javax.swing.JFrame;
  11. import javax.swing.JLabel;
  12. import javax.swing.JMenu;
  13. import javax.swing.JMenuBar;
  14. import javax.swing.JMenuItem;
  15. import javax.swing.JOptionPane;
  16. import java.awt.Dimension;
  17. import java.awt.FlowLayout;
  18. import java.awt.event.MouseEvent;
  19. import java.awt.event.MouseListener;
  20. import java.util.*;
  21.  
  22. public class Main1213 extends JFrame {
  23.      
  24.        int bombNum=30;                       //地雷数目
  25.        int nearBombNum[][]=new int[100][100];       //存储这个格子周围地雷的数目
  26.        int stackNum=0;                              //表示堆栈中有多少个元素,用作while循环的终止条件
  27.        Boolean isBomb[][]=new Boolean [50][50];             //存储格子是不是地雷,false(不是地雷),true(地雷)
  28.        Mybutton button[][]=new Mybutton[100][100];  //Mybutton类型的数组,专门存放按钮,方便得到按钮的x,y参数(坐标参数)
  29.        Stack<Mybutton> a=new Stack<Mybutton>();     //创建一个堆栈对象,用来开图
  30.        static Main1213 b=null;
  31.        
  32.      
  33.         ImageIcon redFlagIcon=new ImageIcon("E:/Michael/javaImage/扫雷图片/1.jpg");       //红旗
  34.         ImageIcon clickIcon=new ImageIcon("E:/Michael/javaImage/扫雷图片/2.jpg");       //鼠标左键单击时的图标
  35.         ImageIcon InitialIcon=new ImageIcon("E:/Michael/javaImage/扫雷图片/3.png");       //初始图片
  36.         ImageIcon mouseOverIcon=new ImageIcon("E:/Michael/javaImage/扫雷图片/4.png");       //鼠标覆盖时的图标
  37.         ImageIcon bombIcon=new ImageIcon("E:/Michael/javaImage/扫雷图片/5.jpg");       //地雷的图标
  38.        
  39.         //地雷数从1-8的对应图标,BombNumberPicture[0]对应图标地雷数为1,BombNumberPicture[7]对应图标地雷数为8
  40.         ImageIcon BombNumberPicture[]={
  41.                                          new ImageIcon("E:/Michael/javaImage/扫雷图片/6.jpg"),  
  42.                                                          new ImageIcon("E:/Michael/javaImage/扫雷图片/7.jpg"),
  43.                                          new ImageIcon("E:/Michael/javaImage/扫雷图片/8.jpg"),
  44.                                          new ImageIcon("E:/Michael/javaImage/扫雷图片/9.jpg"),
  45.                                          new ImageIcon("E:/Michael/javaImage/扫雷图片/10.jpg"),
  46.                                          new ImageIcon("E:/Michael/javaImage/扫雷图片/11.jpg"),
  47.                                          new ImageIcon("E:/Michael/javaImage/扫雷图片/12.jpg"),
  48.                                          new ImageIcon("E:/Michael/javaImage/扫雷图片/13.jpg"),};
  49.  
  50.                        
  51.               public static void main(String[] args)           
  52.               {     b=new Main1213();  
  53.                         b.setBomb();             //布雷
  54.                         b.Mymenu();              //添加菜单栏
  55.                         b.init();                //setVisiable的位置很重要,a.Mymenu();a.init(); 顺序交换就看不到菜单栏了。            
  56.                         b.setButton();           //在界面中添加按钮和监听事件                 
  57.               }
  58.                        
  59.                   public void init()                                                                        
  60.                   {      this.setTitle("扫雷");                                                                                                       //设置窗体的标题        
  61.                          this.setLocationRelativeTo(null);                                                                                          //设置窗体出现位置居中
  62.                          this.setDefaultCloseOperation(3);                                                                                              //设置窗体的关闭操作
  63.                          this.setResizable(true);                                                               //设置禁止调整窗体的大小
  64.                          this.setIconImage((new ImageIcon("E:/Michael/javaImage/扫雷图片/bomb.png").getImage()));//设置标题栏图标      
  65.                          this.setSize(430,500);                                                                                                     //设置窗体的大小                    
  66.                                  this.setLocationRelativeTo(null);                                                      //设置窗体出现在屏幕中间            
  67.                          this.setLayout(new FlowLayout(FlowLayout.LEFT,0,0));          
  68.                          this.setVisible(true);                  
  69.                   }
  70.                        
  71.            public void setButton()                             //绘制界面,鼠标对界面的操作事件(地雷格子)
  72.            {           
  73.                  //事件监听***************************************************************************************************  
  74.                         MouseListener mouseListener=new MouseListener()                        
  75.                         {                    
  76.                             public void mousePressed(MouseEvent e)
  77.                             {  
  78.                             //右键点击********************************************************************
  79.                                 if(e.getButton()==MouseEvent.BUTTON3)
  80.                                 {      
  81.                                    Mybutton btn = (Mybutton)e.getSource();      //得到事件源对象,并强制转型为Mybutton
  82.                                    int flagAndBomb=0;          
  83.            
  84.                                     if(btn.status==0)                                       //如果该按钮状态为没翻转过     
  85.                                                     {btn.setIcon(redFlagIcon);btn.setStatus(4);}     //改变图标为redFlagIcon,并设置为状态3(红旗)
  86.                                                 else if(btn.status==4)                              //如果该按钮状态为红旗   
  87.                                                     {btn.setIcon(InitialIcon);btn.setStatus(0);}     //改变图标为InitialIcon(初始图标)
  88.                                                 else if(btn.status==1)                      //如果是已经翻开的图标
  89.                                                 {
  90.                                                   int x=btn.x, y=btn.y; //x,y用来表示当前按钮的坐标    
  91.                                                   checkBomb(x, y);  
  92.                                                      //如果标记的红旗下面不是地雷,那么游戏结束*********************************
  93.                                                 }
  94.                                    
  95.                            
  96.                                    
  97.                                            //胜利判断**************************
  98.                                            for(int i=0;i<20;i++)                              
  99.                                                for(int j=0;j<20;j++)
  100.                                                { if(isBomb[i][j]&&button[i][j].status==4)
  101.                                                 flagAndBomb++;        
  102.                                                }
  103.                                            if(flagAndBomb==bombNum)
  104.                                         { for(int i=0;i<20;i++)                               //判断胜利后开全图
  105.                                                                for(int j=0;j<20;j++)
  106.                                                                {changeBombIcon(button[i][j]);}                             
  107.                                                        JOptionPane.showMessageDialog(null, "你胜利了");}
  108.                                           //**********************************
  109.                                         }
  110.                             //***************************************************************************
  111.                                
  112.                                
  113.                             //左键点击********************************************************************
  114.                                         if(e.getButton()==MouseEvent.BUTTON1)
  115.                                         { Mybutton btn = (Mybutton)e.getSource();
  116.                                                 if(btn.status==0)
  117.                                                 {   btn.setStatus(1);
  118.                                                         if(!isBomb[btn.x][btn.y])                                  //如果点击不是地雷
  119.                                                              {   findBomb();                         //遍历地图,找到所有位置周围的地雷数目
  120.                                                                      showBomb(btn);                      //根据周围地雷数目,更换图标
  121.                                                                
  122.                                                              }
  123.                                                    
  124.                                                          if(isBomb[btn.x][btn.y])                                             //如果鼠标点击是地雷
  125.                                                              {   for(int i=0;i<20;i++)                              //找到所有的地雷
  126.                                                              for(int j=0;j<20;j++)
  127.                                                              { button[i][j].setStatus(1);                       //改变所有按钮的状态变量为1(翻转状态)
  128.                                                                      if(isBomb[i][j]) button[i][j].setIcon(bombIcon);} //找到地雷并改变图标为bombIcon(地雷图标)                                                                
  129.                                                                  JOptionPane.showMessageDialog(null, "游戏结束");    //弹出消息提示框,提示游戏结束                                                            
  130.                                                              }
  131.                                              }                                 
  132.                                         }
  133.                                 //左键点击**********************************************************************
  134.                             }
  135.  
  136.     //计算点击处周围8个格子中的红旗数,保存在flag,用count来记录红旗和地雷的吻合数目 
  137.         public void checkBomb(int x, int y) {
  138.         int bomb=0,flag=0;                  
  139.                for(int i=0;i<8;i++)
  140.                {
  141.                    if(new Mybutton(getX(x,i),getY(y,i)).locationLegalJudge())   //边界判断
  142.                    {  
  143.        
  144.                            if(button[getX(x,i)][getY(y,i)].status==3||button[getX(x,i)][getY(y,i)].status==4)
  145.                            {
  146.                                    flag++;  //如果格子状态表示红旗,那么红旗数目+1
  147.                                    if(isBomb[getX(x,i)][getY(y,i)])    
  148.                                    {bomb++; }
  149.                            }
  150.                    }   
  151.                }
  152.                                                
  153.    
  154.                                                  //如果红旗和地雷吻合,则开图,不吻合就结束游戏,共2种情况***************************************           
  155.                                                        if(bomb==nearBombNum[x][y]) //如果周围雷数和判断一样
  156.                                                        {    
  157.                                                            for(int i=0;i<8;i++)   //周围8个格子,每个格子判断一次
  158.                                                                        {
  159.                                                                            if(new Mybutton(getX(x,i),getY(y,i)).locationLegalJudge()&&!isBomb[x][y])   //边界判断,而且不是地雷
  160.                                                                            {
  161.                                                                                    changeBombIcon(button[getX(x,i)][getY(y,i)]);   //点击处左上角判断
  162.                                                                                 if(nearBombNum[getX(x,i)][getY(y,i)]==0&&!isBomb[getX(x,i)][getY(y,i)])  
  163.                                                                                          showBomb(button[getX(x,i)][getY(y,i)]);
  164.                                                                                }
  165.                                                                        }
  166.                                                  
  167.                                                        }
  168.                                                  //如果红旗和地雷吻合,则开图,不吻合就结束游戏,共2种情况***************************************
  169.                                                        
  170.                                                      //如果标记的红旗下面不是地雷,那么游戏结束*********************************           
  171.                                                        if ((bomb!=nearBombNum[x][y]&&flag>=nearBombNum[x][y]))           
  172.                                                            {
  173.                                                            for(int i=0;i<20;i++)                              //找到所有的地雷
  174.                                                                      for(int j=0;j<20;j++)
  175.                                                                      { button[i][j].setStatus(1);                       //改变所有按钮的状态变量为1(翻转状态)
  176.                                                                              if(isBomb[i][j]) button[i][j].setIcon(bombIcon);} //找到地雷并改变图标为bombIcon(地雷图标)                                  
  177.                                                                  JOptionPane.showMessageDialog(null, "游戏结束");    //弹出消息提示框,提示游戏结束
  178.                                                        }
  179.                                         }      
  180.                            
  181.                             public void mouseEntered(MouseEvent e)                                
  182.                             {
  183.                        Mybutton btn=(Mybutton)e.getSource();                               //要强制转型
  184.                                if(btn.status==0)   btn.setIcon(mouseOverIcon);                                //如果还没有翻转,那么改变按钮图案
  185.                             }  
  186.                            
  187.                             public void mouseExited(MouseEvent e)
  188.                             {  
  189.                                Mybutton btn=(Mybutton)e.getSource();                               //要强制转型,得到事件源
  190.                                if(btn.status==0)  btn.setIcon(InitialIcon);                                   //如果按钮还未翻转,那么改变按钮图案                        
  191.                             }
  192.                             public void mouseReleased(MouseEvent e)
  193.                             {} 
  194.                             public void mouseClicked(MouseEvent e)
  195.                             {} 
  196.                            
  197.                         };
  198.                       //*******************************************************************************************************
  199.                        
  200.                       //绘制游戏界面************************************************************************************************
  201.                             for(int i=0;i<20;i++)                                   //生成界面按钮20行20列
  202.                                   for(int j=0;j<20;j++)
  203.                                 {  
  204.                                    Mybutton jb=new Mybutton(i,j);                  
  205.                                    jb.setPreferredSize(new Dimension(20,20));                              
  206.                                            jb.addMouseListener(mouseListener);                  //要将new mouselistener的代码放到前面这行代码才不会出错
  207.                                    button[i][j]=jb;                                     //通过这种方式就可以根据i,j唯一确定每个按钮
  208.                                            this.add(jb);                                                    //界面添加按钮
  209.                                 }
  210.                            
  211.                             JLabel jl = new JLabel();                               //用来计时的标签
  212.                             JLabel j2 = new JLabel("游戏计时:");    
  213.                             this.add(j2);
  214.                                 this.add(jl);
  215.                                    //计时功能*********************************************
  216.                                 TimerTask task = new TimerTask()  
  217.                                  {   int n=0;
  218.                                                 public void run()
  219.                                                 {   jl.setText(""+n); n++;}                                             //计时++
  220.                                         };
  221.                                          Timer timer = new Timer();
  222.                                  timer.schedule(task, 0, 1000);
  223.                                //计时功能*********************************************
  224.            
  225.                          //绘制游戏界面************************************************************************************************
  226.            }  
  227.  
  228.            public void setBomb()                               //布雷
  229.            {   for(int i=0;i<20;i++)                           //遍历地图,将所有格子的地雷状态变量都初始化为0,0表示不是地雷
  230.                    for(int j=0;j<20;j++)                           //遍历地图,将所有格子的地雷状态变量都初始化为0,0表示不是地雷
  231.                            isBomb[i][j]=false;                             //遍历地图,将所有格子的地雷状态变量都初始化为0,0表示不是地雷
  232.              int n=0;
  233.               while(n<bombNum)                                 //当n<地雷数,就一直循环执行
  234.               {   int x=new Random().nextInt(20);                         //随机产生行数
  235.                   int y=new Random().nextInt(20);                         //随机产生列数
  236.                    if(!isBomb[x][y]) {isBomb[x][y]=!isBomb[x][y];n++;}   //如果随机产生的位置原来的状态是没有地雷,将地雷状态改变,地雷数加1      
  237.               }
  238.            }
  239.  
  240.             public void findBomb()                              //找出地图中所有位置周围地雷的数目,保存在nearBombNum[x][y]中
  241.            {    for(int x=0;x<20;x++)                           //遍历整个地图
  242.                     for(int y=0;y<20;y++)                                      
  243.                    {
  244.                         if(!isBomb[x][y])                         //只有当这个位置不是地雷的时候才执行查找周围地雷数的代码
  245.                       {
  246.                                 int n=0;                                 //n记录周围地雷的数目
  247.                       for(int i=0;i<8;i++)
  248.                       {
  249.                       if(new Mybutton(getX(x,i),getY(y,i)).locationLegalJudge()&&isBomb[getX(x,i)][getY(y,i)]) //边界判断
  250.                        {
  251.                           n++;
  252.                        }
  253.                       }
  254.                        setNearBombNum(x,y,n);
  255.                            
  256.                       }
  257.                     }
  258.             }
  259.        
  260.            
  261.              public void showBomb(Mybutton btn)                //点击后更改图标和开图功能
  262.             {  
  263.                  int x=btn.x, y=btn.y,k=nearBombNum[x][y];      //x,y用来表示当前按钮的坐标,k用来表示是按钮周围的地雷数      
  264.                     if(btn.status==0) btn.setStatus(1);                             //表示访问过了                     
  265.                    if(k==0)                        //如果这个格子周围没有地雷
  266.                       {  
  267.                            
  268.                            for(int i=0;i<8;i++)
  269.                       {
  270.                       if(new Mybutton(getX(x,i),getY(y,i)).locationLegalJudge()&&!isBomb[getX(x,i)][getY(y,i)]) //边界判断
  271.                        {
  272.                          changeBombIcon(button[getX(x,i)][getY(y,i)]);   //点击处左上角判断
  273.                          if(nearBombNum[getX(x,i)][getY(y,i)]==0&&button[getX(x,i)][getY(y,i)].status==0) {
  274.                            a.push(button[getX(x,i)][getY(y,i)]);
  275.                                        stackNum++;
  276.                                       }
  277.                        }
  278.                       }
  279.  
  280.                                        
  281.                              while(stackNum>0)                           //深度优先遍历,先将所有空格加进去,再倒出来
  282.                             { stackNum--;showBomb(a.pop());}
  283.                        }        
  284.                    
  285.                    else   changeBombIcon(btn);                //如果点击的不是空格,那么直接改变按钮图案        
  286.                    }        
  287.  
  288.                  public void changeBombIcon(Mybutton btn)                 //根据周围地雷数,改变按钮图标
  289.                  {
  290.                  int nearBombNumber=nearBombNum[btn.x][btn.y];                       //k用来表示是按钮周围的地雷数
  291.                  
  292.                  if(nearBombNumber==0){
  293.                                  btn.setIcon(mouseOverIcon);
  294.                              if(isBomb[btn.x][btn.y])  
  295.                              {btn.setIcon(redFlagIcon);btn.setStatus(3);}   //如果是地雷,那么就改变图标
  296.                                        }                 
  297.                  else
  298.                  {
  299.                    btn.setIcon(BombNumberPicture[nearBombNumber-1]); btn.setStatus(1);
  300.                  }
  301.                
  302.                  }
  303.                  //**************************************菜单栏*************************************************//
  304.                  public void Mymenu()
  305.                  {
  306.               JMenu file,edit,help,nandu;//声明JMenu类对象
  307.               JMenuItem newgame,exit,copy,chuji,zhongji,gaoji,author,wanfa;//声明menuitem类对象
  308.              //初始菜单项
  309.                
  310.              
  311.            
  312.               newgame=new JMenuItem("新游戏",new ImageIcon("C:/Users/Administrator/Desktop/images/2.jpg"));  //创建menuItem对象       
  313.                exit=new JMenuItem("关闭"){{b.dispose();}};      //创建menuItem对象
  314.                copy=new JMenuItem("保存战绩"){     //创建menuItem对象
  315.                    { addActionListener(
  316.                                    e->{
  317.                                            JFileChooser a=new JFileChooser();                      //打开文件路径程序框
  318.                                                   a.setDialogTitle("另存为");
  319.                                                   a.showSaveDialog(null) ;                                //注意showSaveDialog和showOpenDialog的区别
  320.                                    });
  321.                    }};    
  322.                    
  323.                author=new JMenuItem("作者"){     //创建menuItem对象
  324.                    { addActionListener(
  325.                                    e->JOptionPane.showMessageDialog(null,"游戏作者:贺思源     制作时间:2014.12.13"));
  326.                    }};    
  327.                    
  328.                wanfa=new JMenuItem("玩法");      //创建menuItem对象
  329.                chuji=new JMenuItem("初级");       //创建menuItem对象
  330.                zhongji=new JMenuItem("中级");       //创建menuItem对象
  331.                gaoji=new JMenuItem("高级");       //创建menuItem对象
  332.        
  333.                
  334.                nandu=new JMenu("难度"){{add(chuji);add(zhongji);add(gaoji);}};      //创建menuItem对象
  335.                help=new JMenu("帮助"){{add(author);add(wanfa); }};         //创建JMenu对象
  336.                file=new JMenu("游戏(G)"){{setMnemonic('G');add(newgame);add(nandu);addSeparator();add(exit);}};       //创建JMenu对象
  337.                edit=new JMenu("编辑"){{add(copy);}};
  338.                JMenuBar menubar=new JMenuBar(){{add(file);add(help);add(edit);}};        //创建menubar对象
  339.                
  340.                
  341.          
  342.                chuji.addActionListener( e->
  343.                {
  344.                    this.dispose();                                             //关闭旧窗体
  345.                         Main1213 s2=new Main1213();
  346.                         s2.setbombNum(30);
  347.                             s2.setBomb();             //布雷
  348.                             s2.Mymenu();              //添加菜单栏
  349.                             s2.init();                //setVisiable的位置很重要,a.Mymenu();a.init(); 顺序交换就看不到菜单栏了。               
  350.                             s2.setButton();           //在界面中添加按钮和监听事件        
  351.                });
  352.                
  353.                zhongji.addActionListener( e->
  354.                {
  355.                    this.dispose();                                             //关闭旧窗体
  356.                         Main1213 s2=new Main1213();
  357.                         s2.setbombNum(60);
  358.                             s2.setBomb();             //布雷
  359.                             s2.Mymenu();              //添加菜单栏
  360.                             s2.init();                //setVisiable的位置很重要,a.Mymenu();a.init(); 顺序交换就看不到菜单栏了。               
  361.                             s2.setButton();           //在界面中添加按钮和监听事件        
  362.                });
  363.                
  364.                gaoji.addActionListener( e->
  365.                {
  366.                    this.dispose();                                             //关闭旧窗体
  367.                         Main1213 s2=new Main1213();
  368.                         s2.setbombNum(90);
  369.                             s2.setBomb();             //布雷
  370.                             s2.Mymenu();              //添加菜单栏
  371.                             s2.init();                //setVisiable的位置很重要,a.Mymenu();a.init(); 顺序交换就看不到菜单栏了。               
  372.                             s2.setButton();           //在界面中添加按钮和监听事件        
  373.                });
  374.                
  375.                exit.addActionListener(e-> this.dispose()); //关闭游戏
  376.                this.setJMenuBar(menubar);                     //设置menuBar
  377.                  }
  378.                  //********************************************************************************************//                
  379.                  
  380.                 public void setbombNum(int x)                      //设置地雷数目
  381.                 {  bombNum=x;}
  382.  
  383.                 public Mybutton getButton(int x,int y) {
  384.                         return button[x][y];
  385.                 }
  386.                
  387.                 //根据x坐标和index,得到周围第i个格子的x坐标
  388.                 public int getX(int x,int index) {
  389.                       int xLocation[]={x-1,x,x+1,x-1,x+1,x-1,x,x+1,};
  390.                         return xLocation[index];
  391.                 }
  392.                
  393.                 //根据y坐标和index,得到周围第i个格子的y坐标
  394.                 public int getY(int y,int index) {
  395.                     int yLocation[]={y+1,y+1,y+1,y,y,y-1,y-1,y-1};
  396.                         return yLocation[index];
  397.                 }
  398.  
  399.                 public int[][] getNearBombNum() {
  400.                         return nearBombNum;
  401.                 }
  402.  
  403.                 public void setNearBombNum(int x,int y,int bombNumber) {
  404.                         nearBombNum[x][y]=bombNumber;
  405.                 }
  406. }
  407.  
  408. 2.Mybutton
  409. package s1213扫雷6;
  410.  
  411. import javax.swing.ImageIcon;
  412. import javax.swing.JButton;
  413. import javax.swing.border.EmptyBorder;
  414.  
  415. public class Mybutton extends JButton {
  416.  
  417.     int status; // 0(未翻转),1(翻转),3(地雷),4(红旗)
  418.         int x, y;
  419.  
  420.         ImageIcon i1 = new ImageIcon("E:/Michael/javaImage/扫雷图片/3.png"); // 初始图片
  421.         EmptyBorder o = new EmptyBorder(2, 2, 0, 0); // 生成按钮边界对象
  422.  
  423.         Mybutton() { // 构造方法
  424.                 this.setIcon(i1); // 给按钮添加图标
  425.                 this.setBorder(o); // 改变按钮边界
  426.         }
  427.  
  428.         Mybutton(int x, int y) { // 调用本类构造方法
  429.                 this();
  430.                 this.x = x;
  431.                 this.y = y;
  432.         }
  433.  
  434.         public boolean locationLegalJudge() {
  435.                 return this.x >= 0 && this.x <=19 && this.y >= 0 && this.y <=19;
  436.         }
  437.  
  438.  
  439.         public void setStatus(int x) // 改变按钮的状态变量方法
  440.         {
  441.                 this.status = x;
  442.         }
  443.  
  444.         public int getStatus() {
  445.                 return status;
  446.         }
  447. }
  448.  

回复 "游戏--扫雷"

这儿你可以回复上面这条便签

captcha