> 文档中心 > JAVA实现经典游戏俄罗斯方块

JAVA实现经典游戏俄罗斯方块


本文代码来源于B站:尚学堂 

博主也在此基础上有些改动,添加了一点提示标签和窗口

本文实现的功能有:

1、 初始化游戏窗口

2、初始化游戏的界面

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

4、随机生成下落方块

5、方块下落速度变化

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

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

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

9、清除方块

10、绘制方块

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

12、游戏的暂停功能 

13、游戏结束后,弹出窗口提示并显示最终分数

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

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("游戏状态:游戏结束!");//弹出窗口提示 JOptionPane.showMessageDialog(null, "游戏结束!最终得分:"+score);    }    //随机生成下落方块形状的方法    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 >=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 >=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 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 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 >=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 >=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 =3&&old6?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&&old17?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 >=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 >=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 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 >=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) {    }}

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

 e11ded1557c64f7d87d12f7153f7d5d0.png

811aacce16d945d7abe3a6399e0abfd0.png

1b046ceef4524570bc8c33bfcd074f02.png

 运行后结果:

 c273e90b9020444d8434ac370108be56.png