当前位置 博文首页 > A16670113506的博客:想不到吧,Java做了个2048小游戏(附源码)

    A16670113506的博客:想不到吧,Java做了个2048小游戏(附源码)

    作者:[db:作者] 时间:2021-09-17 12:21

    对于java初学者来说,通过一些学习小游戏来对swing学习以及对java基础的学习是一个好的方法,同时也给学习带来了很多的乐趣,接下来就给大家分享一个java实现的2048小游戏。

    先来看下效果图:

    好了,废话不多说,直接上代码。大家可以直接复制下面的代码实现体验。需要完整源码的文章末尾可+

    package cn.hangzhou.demo.testOther;
    import java.util.Date;
    import java.util.Random;    // 产生随机数
    import java.awt.event.*;  // 提供各类事件的接口和类
    import java.awt.Color;     // 提供用于颜色的类
    import java.awt.Font;        // 提供与字体相关的类和接口
    import java.awt.EventQueue;  //将来自于基础同位体类和受信任的应用程序类的事件列入队列
    import javax.swing.JFrame;   // 框架
    import javax.swing.JPanel;   // 面板容器  可以加入到 JFrame 中
    import javax.swing.JLabel;   // 显示文本、图像或同时显示二者
    import javax.swing.BorderFactory; // 设计边框
    import javax.swing.SwingConstants;
    import javax.swing.JTextField; // 单行文本输入
    public class my_2048 extends JFrame{
      
      private static final long serialVersionUID = 1L;
      private JPanel ScoresPanel;
      private JPanel MainPanel;
      private JPanel TimeSpentPanel;
      private JPanel TipsPanel;
      
      private JLabel MaxScoreLabel;
      private JLabel CurrentScoreLabel;  // 当前得分
      private JLabel TipsLabel;          // 提示
      private JLabel ScoreValueLabel;    // 当前的分数值
      private JLabel[][] Texts;          // 文本
         private JLabel TimeSpentLabel;     // 显示此次程序运行 经历的时间
         private JLabel TimeSpentValueLabel;
      
      private JTextField MaxScoreField;  // 记录最大分数文本
    //     private JTextField TimeSpentField;      // 记录此次游戏经历的时间的文本框
      
      private int SurDiamonts = 16;      // 表示剩余方块数目
      private int RecordScores = 0;      // 记录当前的分数
      private String CurrentTime = "" ;          // 当前时间
      private int Mark1, Mark2, Mark3, Mark4;  // 判断游戏是否结束
      Font Font1 = new Font("",Font.BOLD,15);
      Font Font2 = new Font("",Font.BOLD,30);
      Random MyRandom = new Random();     // 产生随机数
      
      public  String  Current_time() throws InterruptedException{   // 获取时间
        Date dt = new Date(System.currentTimeMillis());
        while(1>0){
          Thread.sleep(1000);
          dt.setTime(System.currentTimeMillis());
          //CurrentTime = dt.toString();
          return dt.toString();
        }
      }
      //CurrentTime = Current_time();
      
      
      public my_2048() throws InterruptedException{    // 构造方法
        super();
        setResizable(false);   // 设置不允许 调整窗口大小
        getContentPane().setLayout(null); // 设置布局管理器
        setBounds(700, 20, 500, 650);    // 设置在容器中位置 及大小
        setTitle("                                     2048 game ");  // 标题
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭窗口,程序不在内存驻留
        
        TimeSpentPanel = new JPanel();  // 创建时间显示栏
        TimeSpentPanel.setBackground(Color.RED);  // 
        TimeSpentPanel.setBounds(20, 20, 450, 25);
        TimeSpentPanel.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.RED));
        getContentPane().add(TimeSpentPanel);
        TimeSpentPanel.setLayout(null);  //
        
    /*    ScoresPanel = new JPanel();    // 创建计分板
        ScoresPanel.setBackground(Color.GREEN);  // 计分板的背景颜色
        ScoresPanel.setBounds(20, 50, 450, 30);  // 计分板的 位置
        ScoresPanel.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.RED));
        getContentPane().add(ScoresPanel);  // 将计分板添加到窗体
        ScoresPanel.setLayout(null); // 设置布局*/
        
        MainPanel = new JPanel();   // 创建主面板
        MainPanel.setBounds(20, 75, 450, 440);
        //MainPanel.setBackground(Color.BLUE);
        getContentPane().add(MainPanel);
        MainPanel.setLayout(null);
        
        Texts = new JLabel[4][4];
        for(int i = 0; i < 4 ; i++){
          for(int j = 0; j < 4 ;j++){
            Texts[i][j] = new JLabel();   // 创建标签
            Texts[i][j].setFont(Font2);   // 设置字体大小
            Texts[i][j].setHorizontalAlignment(SwingConstants.CENTER);  // 设置文字居中
            Texts[i][j].setBounds(120*i, 115*j, 90 ,90);  // 设置每个框大小,位置
            Texts[i][j].setOpaque(true);   // 
            Texts[i][j].setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.BLACK));
            MainPanel.add(Texts[i][j]);  // 将每个小块加入到  mainPanel 中
          } // for j
        }  // for i
        
        ScoresPanel = new JPanel();    // 创建计分板
        ScoresPanel.setBackground(Color.GREEN);  // 计分板的背景颜色
        ScoresPanel.setBounds(20, 520, 450, 30);  // 计分板的 位置
        ScoresPanel.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.RED));
        getContentPane().add(ScoresPanel);  // 将计分板添加到窗体
        ScoresPanel.setLayout(null); // 设置布局
        
        TipsPanel = new JPanel();  // 提示容器
        TipsPanel.setBackground(Color.YELLOW);
        TipsPanel.setFont(Font1);  // 设置提示字体的大小
        TipsPanel.setBounds(20, 560, 450, 30);
        TipsPanel.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.BLACK));
        getContentPane().add(TipsPanel);
        
        MaxScoreLabel = new JLabel("最高分: ");  // 设置最高分标签
        MaxScoreLabel.setFont(Font1);
        MaxScoreLabel.setBounds(10, 3, 220, 27);
        ScoresPanel.add(MaxScoreLabel);  // 将最高分标签加入到 ScoresPanel 中
        
        ScoreValueLabel = new JLabel("当前得分: "); // 设置当前得分标签
        ScoreValueLabel.setFont(Font1);
        ScoreValueLabel.setBounds(230, 3, 220, 27);  
        //ScoreValueLabel.
        ScoresPanel.add(ScoreValueLabel);
        
        MaxScoreField = new JTextField(" 0");  // 最大分数文本区域
        MaxScoreField.setBackground(Color.GREEN);
        MaxScoreField.setFont(Font1);
        MaxScoreField.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.GREEN));
        MaxScoreField.setBounds(80, 4, 100, 20);
        MaxScoreField.setEditable(false);
        ScoresPanel.add(MaxScoreField);
        
        CurrentScoreLabel = new JLabel(String.valueOf(RecordScores)); // 设置当前得分值标签
        CurrentScoreLabel.setFont(Font1);
        CurrentScoreLabel.setBounds(320, 4, 100, 20);
        CurrentScoreLabel.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.GREEN));
        CurrentScoreLabel.setBackground(Color.red);
        ScoresPanel.add(CurrentScoreLabel);
        
        TipsLabel = new JLabel("请使用小键盘8,2,4,6或者↑,↓,←,→来控制  ^_^");
        TipsLabel.setFont(Font1);
        TipsLabel.setBounds(70, 4, 250, 20);
        TipsPanel.add(TipsLabel); 
        
        TimeSpentLabel = new JLabel("游戏开始时间为 : ");
        TimeSpentLabel.setFont(Font1);
        TimeSpentLabel.setBounds(20, 3, 150, 27);
        TimeSpentPanel.add(TimeSpentLabel);
        
        //SimpleDateFormat dt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //CurrenTime = dt.format(new Date());
        //System.out.println(CurrenTime);
        
        TimeSpentValueLabel = new JLabel(String.valueOf(CurrentTime));
        TimeSpentValueLabel.setFont(Font1);
        TimeSpentValueLabel.setBounds(160, 3, 300, 27);
        TimeSpentPanel.add(TimeSpentValueLabel);
        TimeSpentValueLabel.setText(String.valueOf(Current_time()));
        
        MaxScoreField.addKeyListener(new KeyAdapter() {  // 为最高分标签添加监听器
          public void keyPressed(KeyEvent e){
            Major(e);
          }
        });    
        Creat_2();   // 产生俩个 新的 2
        Creat_2();
      } // my_2048
      protected void SetColor(int i,int j,String str){  //  对某数字个方块进行颜色的设置
        switch(str){
        case "" :
        case "2" :
          Texts[i][j].setBackground(Color.WHITE);  // 浅灰
          break;
        case "4" :
          Texts[i][j].setBackground(Color.LIGHT_GRAY);  
          break;
        case "8" :
          Texts[i][j].setBackground(Color.YELLOW);  // 橙色
          break;
        case "16" :
          Texts[i][j].setBackground(Color.ORANGE);
          break;
        case "32" :
          Texts[i][j].setBackground(Color.PINK);
          break;
        case "64":
          Texts[i][j].setBackground(Color.RED);
          break;
        case "128":
          Texts[i][j].setBackground(Color.MAGENTA);
          break;
        case "256":
          Texts[i][j].setBackground(Color.GREEN);
          break;
        case "512" :
          Texts[i][j].setBackground(Color.BLUE);
          break;
        case "1024":
          Texts[i][j].setBackground(Color.GRAY);
          break;
        case "2048" :
          Texts[i][j].setBackground(Color.LIGHT_GRAY);
          break;
        case "4096" :
          Texts[i][j].setBackground(Color.DARK_GRAY);
          break;
        default:
            break;
        } // switch
      } // SetColor
      protected void Creat_2(){  // 新产生一个 2 
        int i ,j;
        boolean r = false;
        String str;
        
        if(SurDiamonts > 0){  // 如果剩余方块
          while(!r){
            i = MyRandom.nextInt(4);
            j = MyRandom.nextInt(4);
            str = Texts[i][j].getText();
            if((str.compareTo("") == 0)){
              //texts[i][j].setIcon(icon2);
              Texts[i][j].setText("2");
              SetColor(i, j, "2");
              
              SurDiamonts --;  // 剩余方块数减 1
              r = true;
              Mark1 = Mark2 = Mark3 = Mark4 = 0;  
            }
          }
        }
        else if(Mark1 >0 && Mark2 >0 && Mark3 > 0 && Mark4 > 0){    // mark1 到mark4同时被键盘赋值为1说明任何方向键都不能产生新的数字2,说明游戏失败
            TipsLabel.setText("    GAME OVER !");
          
        }
      }  // Craet
      protected void Major(final KeyEvent e){  // 对相应动作做出的反应
        int KeyCode = e.getKeyCode();  // 获取按键代码
        int Pre;   // 防止连加
        int Num;
        String Str;
        String Str_1;
        switch (KeyCode){
        
        case KeyEvent.VK_4 :
        case KeyEvent.VK_LEFT :  // 当键盘输入 ← 或者 4时
          for(int j = 0; j < 4; j++){
            Pre = 5;
            for(int k = 0; k < 3; k++){
              for(int i = 1; i < 4; i++){    // 遍历 16 个空格
                Str = Texts[i][j].getText();   // 获取当前空格的内容
                Str_1 = Texts[i - 1][j].getText();  // 获得当前当前空格左边的第一个空格的内容
              
                if(Str_1.compareTo("") == 0){  // 如果当前空格的左边第一个空格内容为空
                  Texts[i - 1][j].setText(Str);  // 设定 左 1 的值为 当前方块的值
                  SetColor(i-1, j, Str);  //  设定左 1 的颜色
                  Texts[i][j].setText("");  // 将当前方块的值置为 空
                  SetColor(i, j, "");   // 设定当前方块的颜色
                }  // if 左 1 内容为空
                else if(Str.compareTo(Str_1) == 0 && i != Pre && i != Pre -1){  // 俩个方框内容相等  且  没发生多次相加情况
                  Num  = Integer.parseInt(Str);  // 将当前方框的 内容转化 为 整型
                  RecordScores += Num ;  //  记录的当前得分 增加
                  SurDiamonts ++;    // 空余方格的数目增加
                  Str = String.valueOf(2 * Num);  
                  Texts[i - 1][j].setText(Str);  // 将两个数相加后 添加到 左 1
                  SetColor(i-1, j, Str);  // 给左 1 设置颜色
                  Texts[i][j].setText("");  // 将当前方块 值 置为 空 
                  SetColor(i, j, "");
                  Pre = i;
                } // else if  两个方块值相等 且
              } // for  i
            }  // for k
          }  // for j
          Mark3 = 1;
          Creat_2();  // 创建一个新的 2 
          break;
        case KeyEvent.VK_6 :
        case KeyEvent.VK_RIGHT :   // 键盘输入 → 或者 2
          for(int j = 0; j < 4; j ++){
            Pre = 5;
            for(int k = 0; k < 5; k++){
              for(int i = 2; i >= 0; i--){
                Str = Texts[i][j].getText();
                Str_1 = Texts[i + 1][j].getText();
                
                if(Str_1.compareTo("") == 0){
                  Texts[i + 1][j].setText(Str);
                  SetColor(i+1, j, Str);
                  Texts[i][j].setText("");
                  SetColor(i, j, "");
                }
                else if(Str.compareTo(Str_1) == 0 && i != Pre && i != Pre + 1){
                  Num  = Integer.parseInt(Str);
                  RecordScores += Num ;
                  SurDiamonts ++;
                  Str = String.valueOf(2 * Num);
                  Texts[i + 1][j].setText(Str );
                  SetColor(i+1, j, Str);
                  Texts[i][j].setText("");
                  SetColor(i, j, "");
                  Pre= i;
                }
              }
            }
          }
          Mark4 = 1;
          Creat_2();
          break;
        case KeyEvent.VK_2 :
        case KeyEvent.VK_DOWN :   // 当键盘 ↓ 或者 2 时
          for(int i = 0; i < 4; i ++){
            Pre = 5;
            for(int k = 0; k < 3; k++){
              for(int j = 2; j >= 0; j--){  // 遍历16个方格
                Str = Texts[i][j].getText();  // 获得当前空格的内容
                Str_1 = Texts[i][j + 1].getText();  // 获取当前空格下面第一个空格的内容
                
                if(Str_1.compareTo("") == 0){   // 当 当前空格下面的第一个空格为空
                  Texts[i][j + 1].setText(Str);
                  SetColor(i, j+1, Str);
                  Texts[i][j].setText("");
                  SetColor(i, j, "");
                }  // if 当前空格下面第一个空格的内容为空
                else if(Str.compareTo(Str_1) == 0 && j !=Pre && j != Pre+ 1){
                  Num  = Integer.parseInt(Str);
                  RecordScores += Num ;
                  SurDiamonts ++;
                  Str = String.valueOf(2 * Num);
                  Texts[i][j + 1].setText(Str);
                  SetColor(i, j+1, Str);
                  Texts[i][j].setText("");
                  SetColor(i, j, "");
                  Pre = j;
                }
              }  // for j
            }  // for k
          }  // for i
          Mark2 = 1;
          Creat_2();
          break;
        case KeyEvent.VK_8 :
        case KeyEvent.VK_UP:   // 按键为← 或者 4 
          for(int i = 0; i < 4;i++){
            Pre = 5;
            for(int j = 0; j < 3;j++){
              for(int k = 1;k < 4;k++){  // 遍历全部方块
                Str = Texts[i][k].getText();  // 获取当前位置的字符
                Str_1 = Texts[i][k-1].getText(); // 获取当前位置的上边的第一个字符
                
                if(Str_1.compareTo("") == 0){  // 如果左边第一个字符为空
                  Texts[i][k-1].setText(Str);  // 将字符左移(字符赋值)
                  SetColor(i, k-1, Str);
                  Texts[i][k].setText("");   // 当前字符置为 空
                  SetColor(i, k, "");
                } // if
                else if ((Str.compareTo(Str_1) == 0) && (k != Pre) &&( k != Pre-1)) {  // 如果当前字符和左边第一个字符相等
                  Num = Integer.parseInt(Str); // 将字符型变量转化为整型变量
                  RecordScores += Num;  // 记录的当前分数要增加
                  SurDiamonts ++;   // 剩余的空方格的数目增加
                  Str = String.valueOf(2 * Num);  // str 的值 增加一倍
                  Texts[i][k-1] .setText(Str);  // 左边的第一个方块字符变成俩倍
                  SetColor(i, k-1, Str);  // 给左边的方块改变颜色
                  Texts[i][k].setText("");  // 当前方块值置空
                  SetColor(i, k, "");
                  Pre = k;
                }
              } // for k
            }  // for j
          } // for i
          Mark1 = 1;
          Creat_2();  // 新产生一个 2 
        default:
          break;
        } // switch
        
        CurrentScoreLabel.setText(String.valueOf(RecordScores));
      }
      public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        EventQueue.invokeLater(new Runnable(){   // 创建一个线程  好处:这个方法调用完毕后,它会被销毁
          public void run(){
            try{
              my_2048 frame = new my_2048();
              frame.setVisible(true);
            //  Thread thread = new Thread(frame);
            //  thread.start();
            }
            catch(Exception e1){   // 捕捉异常
              e1.printStackTrace();
            }
          }
        });
      }
    }

    当然啦,方便大家有个好的学习技术交流,这里建立了交流群:716743415,或者备注“996”,添加VX噢

    ?

    ?

    cs