Java实现俄罗斯方块的源码分享

作者:遇安.112 时间:2023-02-17 04:20:48 

本文实现的功能有:

1、 初始化游戏窗口

2、初始化游戏的界面

3、初始化游戏的说明面板

4、随机生成下落方块

5、方块下落速度变化

6、判断方块是否可以下落

7、移除某一行方块上面的方块后让上面的方块掉落

8、刷新移除某一行方块后的界面

9、清除方块

10、绘制方块

11、键盘控制方块的移动、变形和快速下落

12、游戏的暂停功能 

三小时纯手工打造,具体实现代码: 

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

public class start extends JFrame implements KeyListener {
   public static void main(String[] args) throws Exception {
    //   SwingUtilities.invokeLater(start::initWindow);
       start t=new start();
       t.game_begin();
   }
   //游戏的行数为26,列数为12
   private static final int game_x=26;
   private static final int game_y=12;

//文本域数组
   JTextArea[][] text;
   //二维数组
   int [][] data;
   //显示游戏状态的标签
   JLabel Label1;
   //显示游戏分数的标签
   JLabel Label;
   //提示暂停键的标签
   JLabel label;
   //用于判断游戏是否结束
   boolean isrunning;
   //用于存储所有方块的数组
   int [] allRect;
   //用于存储当前方块的变量
   int rect;
   //线程的休眠时间
   int time=1000;
   //表示方块坐标
   int x,y;
   //该变量用于计算得分
   int score=0;
   //定义一个标志变量,判断游戏是否暂停
   boolean game_pause=false;
   //定义一个变量,用于记录按下暂停的次数
   int pause=0;

public void initWindow(){
       //设置窗口大小
       this.setSize(600,850);
       //设置窗口是否可见
       this.setVisible(true);
       //设置窗口居中
       this.setLocationRelativeTo(null);
       //设置释放窗体
       this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       //设置窗体大小不可变
       this.setResizable(false);
       //设置标题
       this.setTitle("俄罗斯方块");

}
   public start(){
       text=new JTextArea[game_x][game_y];
       data=new int[game_x][game_y];
       //初始化游戏状态的标签
       Label1 =new JLabel("游戏状态:正在游戏中!");
       //初始化游戏分数的标签
       Label=new JLabel("游戏得分:0");
       //初始化提示标签
       label=new JLabel("按下s键,即可暂停游戏!");
       initGamePanel();
       initExplainPanel();
       initWindow();
       //初始化游戏开始的标志
       isrunning=true;
       //初始化存放方块的数组
       allRect =new int[]{0x00cc,0x8888,0x000f,0x888f,0xf888,0xf111,0x111f,0x0eee,0xffff,0x0008
               ,0x0888,0x000e,0x0088,0x000c,0x08c8,0x00e4,0x04c4,0x004e,0x08c4,0x006c,0x04c8,0x00c6};
   }
   //初始化游戏界面
   public void initGamePanel(){
       JPanel game_main=new JPanel();
       game_main.setLayout(new GridLayout(game_x,game_y,1,1));

for (int i = 0; i < text.length; i++) {
           for (int j = 0; j < text[i].length; j++) {
               //设置文本域的行列数
               text[i][j]=new JTextArea(game_x,game_y);
               //设置文本域的背景颜色
               text[i][j].setBackground(Color.WHITE);//白色
               //添加键盘监听事件
               text[i][j].addKeyListener(this);
               //初始化游戏边界
               if(j==0 || j==text[i].length-1 || i==text.length-1){
                   text[i][j].setBackground(Color.BLACK);//设置为黑色,这里看个人喜好设置
                   data[i][j]=1;//表示这里有方块
               }
               //设置文本域不可编辑
               text[i][j].setEditable(false);
               //文本区域添加到主面板上去
               game_main.add(text[i][j]);
           }
       }
       //将主面板添加到窗口中
       this.setLayout(new BorderLayout());
       this.add(game_main,BorderLayout.CENTER);//把游戏区域添加到窗口的中间
   }
   //初始化游戏的说明界面
   public void initExplainPanel(){
       //创建游戏的左说明面板
       JPanel explain_left=new JPanel();
       //创建游戏的右说明面板
       JPanel explain_right=new JPanel();
       //初始化格式布局
       explain_left.setLayout(new GridLayout(4,1));
       explain_right.setLayout(new GridLayout(3,1));
       //在左说明面板,添加说明文字
       explain_left.add(new JLabel("按空格键,方块变形"));
       explain_left.add(new JLabel("按左箭头,方块左移"));
       explain_left.add(new JLabel("按右箭头,方块右移"));
       explain_left.add(new JLabel("按下箭头,方块下落"));
       //设置游戏标签的内容为红色字体
       Label1.setForeground(Color.RED);
       //将游戏状态和得分、提示添加到右面板上
       explain_right.add(label);
       explain_right.add(Label);
       explain_right.add(Label1);
       //将左说明面板添加到窗口左侧
       this.add(explain_left,BorderLayout.WEST);
       //将右说明面板添加到窗口右侧
       this.add(explain_right,BorderLayout.EAST);

}
   //开始游戏的方法
   public void game_begin() throws Exception {
       while (true){
           //判断游戏是否结束
           if(!isrunning){
               break;
           }
           //进行游戏
           game_run();
       }
       //在标签位置显示游戏结束
       Label1.setText("游戏状态:游戏结束!");
   }
   //随机生成下落方块形状的方法
   public void ranRect(){
       Random random=new Random();

rect=allRect[random.nextInt(22)];
   }
   //游戏运行的方法
   public void game_run() throws Exception {
       ranRect();
       //方块下落位置
       x=0;
       y=5;
       for (int i = 0; i < game_x; i++) {
           Thread.sleep(time);
           if (game_pause) {
               i--;
           } else {
           //判断方块是否可以下落
           if (!canFall(x, y)) {
               //将data变成1,表示有方块占用
               changData(x, y);
               //循环遍历4层,看是否有行可以消除
               for (int j = x; j < x + 4; j++) {
                   int sum = 0;
                   for (int k = 1; k <= (game_y - 2); k++) {
                       if (data[j][k] == 1) {
                           sum++;
                       }
                   }
                   //判断是否有一行可以被消除
                   if (sum == (game_y - 2)) {
                       //消除J这一行
                       removeRow(j);
                   }
               }
               //判断游戏是否失败
               for (int j = 1; j < (game_y - 2); j++) {
                   if (data[3][j] == 1) {
                       isrunning = false;
                       break;
                   }
               }
               break;//方块无法下落,我们应该重新生成一个方块,并重新遍历26层
           } else {
               //方块可以下落,层数加一
               x++;
               //方块下落一格
               fall(x, y);
           }
       }
       }
   }
   //判断方块是否可以继续下落的方法
   public boolean canFall(int m,int n){
       //定义一个变量
       int temp=0x8000;
       //遍历4*4方格
       for (int i = 0; i <4 ; i++) {
           for (int j = 0; j < 4; j++) {
               if((temp & rect)!=0){
                   //判断该位置的下一行是否有方块
                   if(data[m+1][n]==1){
                       return false;
                   }
               }
               n++;
               temp >>=1;//右移一位
           }
           m++;
           n=n-4;//让n回归首列
       }
       //循环结束,可以下落
       return true;
   }
   //改变不可下降的方块对应的区域的值的方法
   public void changData(int m,int n){
       //定义一个变量
       int temp=0x8000;
       //遍历整个4*4的方块
       for (int i = 0; i < 4; i++) {
           for (int j = 0; j < 4; j++) {
               if((temp & rect)!=0){
                   data[m][n]=1;
               }
               n++;
               temp >>=1;//右移一位
           }
           m++;
           n=n-4;
       }
   }
   //移除某一行的所有方块,并让上面的方块掉落的方法
   public void removeRow(int row){
       int temp=100;
       for (int i = row; i >=1 ; i--) {
           for (int j = 1; j <=(game_y-2) ; j++) {
               //进行覆盖
               data[i][j]=data[i-1][j];

}
       }
       //刷新游戏区域
       reflesh(row);
       //方块加速
       if(time>temp){
           time-=temp;
       }
       //每消除一行,得分加100
       score+=temp;
       //显示变化后的分数
       Label.setText("游戏得分:"+score);
   }
   //刷新移除某一行后的游戏界面的方法
   public void reflesh(int row){
       //遍历row上面的游戏区域
       for (int i = row; i >=1 ; i--) {
           for (int j = 1; j <=(game_y-2) ; j++) {
               if(data[i][j]==1){//如果是方块,将方块设置为蓝色
                   text[i][j].setBackground(Color.BLUE);
               }else{//如果不是方块,说明是游戏的背景区域
                   text[i][j].setBackground(Color.WHITE);//设置为白色
               }
           }
       }
   }
   //方块向下掉落一层的方法
   public void fall(int m,int n){
       if(m>0){
           //清除上一层方块
           clear(m-1,n);
       }
       //重新绘制方块
       draw(m,n);
   }
   //清除方块掉落后,上一层有颜色的地方的方法
   public void clear(int m,int n){
       //定义一个变量
       int temp=0x8000;
       for (int i = 0; i < 4; i++) {
           for (int j = 0; j < 4; j++) {
               if ((temp & rect) != 0) {
                   text[m][n].setBackground(Color.WHITE);//将其设置成背景颜色,相当于消除
               }
               n++;
               temp >>=1;//右移一位
           }
           m++;
           n=n-4;
       }
   }
   //重新绘制掉落后的方块的方法
   public void draw(int m,int n){
       //定义一个变量
       int temp=0x8000;
       for (int i = 0; i < 4; i++) {
           for (int j = 0; j < 4; j++) {
               if((temp & rect)!=0){
                   text[m][n].setBackground(Color.BLUE);//设置成之前的方块颜色
               }
               n++;
               temp >>=1;//右移一位
           }
           m++;
           n=n-4;
       }
   }

@Override
   public void keyTyped(KeyEvent e) {
       //控制游戏暂停
       if(e.getKeyChar()=='s'){//如果按下s,则游戏暂停
           //判断游戏是否结束
           if(!isrunning){
               return;
           }
           pause++;
           //判断是按下一次,暂停游戏
           if(pause==1){
               game_pause=true;
               Label1.setText("游戏状态:暂停中!");
           }
           //判断是按下两次,继续游戏
           if(pause==2){
               game_pause=false;
               pause=0;//重置暂停次数
               Label1.setText("游戏状态:正在游戏中!");
           }
       }

//控制方块进行变形
       if(e.getKeyChar()==KeyEvent.VK_SPACE){
           //判断游戏是否结束
           if(!isrunning){
               return;
           }
           //判断游戏是否暂停
           if(game_pause){
               return;
           }
           //定义变量,存储目前方块的索引
           int old;
           for (old = 0; old < allRect.length; old++) {
               //判断是否是当前方块
               if(rect==allRect[old]){
                   break;
               }
           }
           //定义变量,存储变形后的方块
           int next;
           //判断是完整方块
           if(old==0||old==7||old==8||old==9){
               return;
           }
           //清除当前方块
           clear(x,y);
           if(old==1||old==2){
               next=allRect[old==1?2:1];
               //如果可以变形
               if(canTurn(next,x,y)){
                   rect=next;
               }
           }
           if(old>=3&&old<=6){
               next=allRect[old+1>6?3:old+1];
               if(canTurn(next,x,y)){
                   rect=next;
               }
           }
           if(old==10||old==11){
               next=allRect[old==10?11:10];
               if(canTurn(next,x,y)){
                   rect=next;
               }
           }
           if(old==12||old==13){
               next=allRect[old==12?13:12];
               if(canTurn(next,x,y)){
                   rect=next;
               }
           }
           if(old>=14&&old<=17){
               next=allRect[old+1>17?14:old+1];
               if(canTurn(next,x,y)){
                   rect=next;
               }
           }
           if(old==18||old==19){
               next=allRect[old==18?19:18];
               if(canTurn(next,x,y)){
                   rect=next;
               }
           }
           if(old==20||old==21){
               next=allRect[old==20?21:20];
               if(canTurn(next,x,y)){
                   rect=next;
               }
           }
           //重新绘制变形后的方块
           draw(x,y);
       }
   }
   public boolean canTurn(int a,int m,int n){
       //创建变量
       int temp=0x8000;
       //遍历整个方块
       for (int i = 0; i < 4; i++) {
           for (int j = 0; j < 4; j++) {
               if ((temp & rect) != 0) {
                   if(data[m][n]==1){
                       return false;
                   }
               }
               n++;
               temp >>=1;
           }
           m++;
           n=n-4;
       }
       //可以变形
       return true;
   }

@Override
   public void keyPressed(KeyEvent e) {
       //方块进行左移
       if(e.getKeyCode()==37){//左箭头对应的数值为37
           //判断游戏是否结束
           if(!isrunning){
               return;
           }
           //判断游戏是否暂停
           if(game_pause){
               return;
           }
           //方块是否碰到左墙壁
           if(y<=1){
               return;
           }
           //方块的左边是否有方块
           int temp=0x8000;
           for (int i = x; i <x+4 ; i++) {
               for (int j = y; j <y+4 ; j++) {
                   if((temp & rect)!=0){
                       if(data[i][j-1]==1){
                           return;
                       }
                   }
                   temp >>=1;
               }
           }
           //清除目前方块
           clear(x,y);
           y--;//向左移动
           draw(x,y);//重新绘制出向左移动后的方块
       }
       //方块进行右移
       if(e.getKeyCode()==39) {//右箭头对应的数值为39
           //判断游戏是否结束
           if(!isrunning){
               return;
           }
           //判断游戏是否暂停
           if(game_pause){
               return;
           }
           int temp=0x8000;
           int m=x;
           int n=y;
           //存储最右边的坐标值
           int num=1;
           for (int i = 0; i < 4; i++) {
               for (int j = 0; j < 4; j++) {
                   if ((temp & rect) != 0) {
                       if(n>num){
                           num=n;
                       }
                   }
                   n++;
                   temp >>=1;
               }
               m++;
               n=n-4;
           }
           //判断是否碰到右墙壁
           if(num>=(game_y-2)){
               return;
           }
           //判断方块右移途中是否碰到其他方块
           temp=0x8000;
           for (int i = x; i <x+4 ; i++) {
               for (int j = y; j < y + 4; j++) {
                   if ((temp & rect) != 0) {
                       if(data[i][j+1]==1){
                           return;
                       }
                   }
                   temp>>=1;
               }
           }
           //清除当前方块
           clear(x,y);
           y++;//右移一位
           draw(x,y);//重新绘制出向右移动后的方块
       }
       //方块进行下落
       if(e.getKeyCode()==40) {//下箭头对应的数值为40
           //判断游戏是否结束
           if (!isrunning) {
               return;
           }
           //判断游戏是否暂停
           if(game_pause){
               return;
           }
           //判断方块是否可以下落
           if(!canFall(x,y)){
               return;
           }
           //清除当前方块
           clear(x,y);
           //改变方块坐标
           x++;
           draw(x,y);//重新绘制出向右移动后的方块
       }
   }

@Override
   public void keyReleased(KeyEvent e) {

}
}

 其中的方块数组中的数字意义:

Java实现俄罗斯方块的源码分享

Java实现俄罗斯方块的源码分享

Java实现俄罗斯方块的源码分享

运行后结果:

Java实现俄罗斯方块的源码分享

来源:https://blog.csdn.net/qq_62731133/article/details/124787011

标签:Java,俄罗斯方块
0
投稿

猜你喜欢

  • Android亮屏速度分析总结

    2023-11-06 11:55:21
  • SWT(JFace)体验之模拟BorderLayout布局

    2022-08-17 18:09:51
  • java 中clone()的使用方法

    2023-03-31 12:11:37
  • SpringMVC实现文件上传下载功能

    2023-09-05 19:49:39
  • C#开发Windows服务实例之实现禁止QQ运行

    2023-04-13 03:29:29
  • C#将配置文件appsetting中的值转换为动态对象调用

    2023-11-28 01:29:53
  • C#中GDI+绘制圆弧及圆角矩形等比缩放的绘制

    2022-06-14 21:15:05
  • 详解Mybatis极其(最)简(好)单(用)的一个分页插件

    2021-09-25 03:00:35
  • Java中构造函数,set/get方法和toString方法使用及注意说明

    2021-07-15 13:01:39
  • Android中初始化Codec2的具体流程

    2023-08-27 21:30:32
  • Java shiro安全框架使用介绍

    2023-07-09 05:24:35
  • Android中资源文件用法简单示例

    2023-09-24 22:29:04
  • Android自定义UI手势密码终结版

    2021-07-29 15:40:17
  • 浅谈一下Java的双亲委派模式

    2021-11-12 02:48:17
  • Java中final与继承操作实例分析

    2023-09-14 08:56:02
  • Android 之BottomsheetDialogFragment仿抖音评论底部弹出对话框效果(实例代码)

    2023-08-06 01:01:56
  • 详解java中String、StringBuilder、StringBuffer的区别

    2023-06-17 06:03:23
  • java实现幸运抽奖功能

    2023-11-27 07:24:16
  • Android应用自动更新功能实现的方法

    2022-12-02 07:01:53
  • mybatis 集合嵌套查询和集合嵌套结果的区别说明

    2022-10-12 15:17:02
  • asp之家 软件编程 m.aspxhome.com