Java俄罗斯方块
遇安.112 人气:0本文实现的功能有:
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) { } }
其中的方块数组中的数字意义:
运行后结果:
加载全部内容