Java实现俄罗斯方块的源码分享
作者:遇安.112
俄罗斯方块是一个最初由阿列克谢帕吉特诺夫在苏联设计和编程的益智类视频游戏。本文将利用Java语言实现这一经典的小游戏,感兴趣的可以学习一下
本文实现的功能有:
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俄罗斯方块内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!