我们学面向对象的时候曾经做过俄罗斯方块这个案例,当时没有做完,我也不知道有《JAVA经典项目集锦》这个教材(做飞机大战的时候老师才告诉我们有这个书)。我当时想把它完成,可是自己又水平不够,不会JFrame,不会操纵图片,不会定时器,不会监听键盘,感觉难以下手。所以我在网上找了一个别人做的俄罗斯方块程序,把它小幅修改了一下,分享给大家。

即使你对我们已经做过的俄罗斯方块项目已经非常熟了,也可以看看这个程序。这个程序比起来《JAVA经典项目集锦》上面完整版的俄罗斯方块项目的优点在于精简,它就是为了实现俄罗斯方块运行时的效果而写的程序,能少写则少写,最终不到300行完成这个程序。而我们的项目为了教学,刻意使用了很多的类,使得最终程序很长(我没有敲一遍,估计不算注释要有600行)。这个程序节省篇幅的地方主要就在于它只用了一个三维数组,36行代码就把7种形状,4种旋转状态全部包括进去了,而我们的案例中采用了1个类(包括8个内部类),总共200行代码才做到同样的效果,而且,对这些类的操作也比对一个数组操作要更加麻烦,又在操作这些形状上拉开200行代码的差距。因此,虽然面向对象有很多好处,但是滥用面向对象也会招致很多不必要的麻烦,比如编写代码篇幅剧增,使得编程花费时间增加。

此程序除了没有用图片,直接用黑块代替cell的图片,实际游戏效果几乎和案例的一样,它也实现了计分和让速度等级随着游戏的进行递增。大家可以阅读一下,和我们做的案例对比一下,反思如果你自己编写一个程序,如何能尽量缩短程序的篇幅,兼顾写代码的效率和代码性能。

 

package Tetris; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import javax.swing.*; import javax.swing.Timer; public class Tetris extends JFrame{         public Tetris(){                 Tetrisblok a=new Tetrisblok();                 addKeyListener(a);                 add(a);         }         public static void main(String[] args){                 Tetris frame=new Tetris();                 JMenuBar menu=new JMenuBar();                 frame.setJMenuBar(menu);                 JMenu game=new JMenu("游戏");                 JMenuItem newgame=game.add("新游戏");                 JMenuItem pause=game.add("暂停");                 JMenuItem goon=game.add("继续");                 JMenuItem exit=game.add("退出");                 JMenu help=new JMenu("帮助");                 JMenuItem about=game.add("关于");                 menu.add(game);                 menu.add(help);                 frame.setLocationRelativeTo(null);                 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);                 frame.setSize(220,275);                 frame.setTitle("Tetris内测版");                 frame.setVisible(true);                 frame.setResizable(false);                         } } class        Tetrisblok extends JPanel implements KeyListener{         private int level=1;         private int sum=0;         private int blockType;         private int score=0;         private int turnState;         private int x;         private int y;         private int i=0;         int j=0;         int flag=0;         int[][]map=new int[13][23];         private final int shapes[][][]=new int[][][]{         //i                         {        {0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0},                                 {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0},                                 {0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0},                                 {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}        },         //s                         {        {0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0},                                 {1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0},                                 {0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0},                                 {1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0}        },         //z                         {        {1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0},                                 {0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0},                                 {1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0},                                 {0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0}        },         //j                         {        {0,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0},                                 {1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},                                 {1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0},                                 {1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0}        },         //o                         {        {1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},                                 {1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},                                 {1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},                                 {1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}        },         //l                         {        {1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0},                                 {1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0},                                 {1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0},                                 {0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0}        },         //t                         {        {0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0},                                 {0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0},                                 {1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0},                                 {0,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0}        }         };         public void newblock(){                 sum++;                 if(sum%20==0){                         level++;                 }                 blockType=(int)(Math.random()*1000)%7;                 turnState=(int)(Math.random()*1000)%4;                 x=4;                 y=0;                 if(gameover(x,y)==1){                         newmap();                         drawwall();                         score=0;                         level=1;                         JOptionPane.showMessageDialog(null, "GAME OVER");                 }         }         public void drawwall(){                 for(i=0;i<12;i++){                         map[i][21]=2;                 }                 for(j=0;j<22;j++){                         map[11][j]=2;                         map[0][j]=2;                 }         }         public void newmap(){                 for(i=0;i<12;i++){                         for(j=0;j<22;j++){                                 map[i][j]=0;                         }                 }         }         Tetrisblok(){                 newblock();                 newmap();                 drawwall();                 Timer timer=new Timer(700/level,new TimerListener());                 timer.start();         }         public void turn(){                 int tempturnState=turnState;                 turnState=(turnState+1)%4;                 if(blow(x,y,blockType,turnState)==1){                 }                 if(blow(x,y,blockType,turnState)==0){                         turnState=tempturnState;                 }                 repaint();         }         public void left(){                 if(blow(x-1,y,blockType,turnState)==1){                         x=x-1;                 }                 ;                 repaint();         }         public void right(){                 if(blow(x+1,y,blockType,turnState)==1){                         x=x+1;                 }                 ;                 repaint();         }         public void down(){                 if(blow(x,y+1,blockType,turnState)==1){                         y=y+1;                         delline();                 }                 if(blow(x,y+1,blockType,turnState)==0){                         add(x,y,blockType,turnState);                         newblock();                         delline();                 }                 ;                 repaint();         }         public int blow(int x, int y, int blocktype,int turnState){                 for(int a=0;a<4;a++){                         for(int b=0;b<4;b++){                                 if(((shapes[blockType][turnState][a*4+b]==1)&&(map[x+b+1][y+a]==1))||                                                 ((shapes[blockType][turnState][a*4+b]==1)&&(map[x+b+1][y+a]==2))){                                         return 0;                                 }                         }                 }                 return 1;         }         public void delline(){                 int c=0;                 int d1=0;                 for(int b=0;b<22;b++){                         for(int a=0;a<12;a++){                                 if(map[a][b]==1){                                         c=c+1;                                         if(c==10){                                                 d1+=10;                                                 score+=d1;                                                 for(int d=b;d>0;d--){                                                         for(int e=0;e<11;e++){                                                                 map[e][d]=map[e][d-1];                                                         }                                                 }                                         }                                 }                         }                         c=0;                 }         }         public int gameover(int x,int y){                 if(blow(x,y,blockType,turnState)==0){                         return 1;                 }                 return 0;         }         public void add(int x,int y,int blockType,int turnState){                 int j=0;                 for(int a=0;a<4;a++){                         for(int b=0;b<4;b++){                                 if(map[x+b+1][y+a]==0){                                         map[x+b+1][y+a]=shapes[blockType][turnState][j];                                 }                                 ;                                 j++;                         }                 }         }         public void paintComponent(Graphics g){                 super.paintComponent(g);                 for(j=0;j<16;j++){                         if(shapes[blockType][turnState][j]==1){                                 g.fillRect((j%4+x+1)*10,(j/4+y)*10,10,10);                         }                 }                 for(j=0;j<22;j++){                         for(i=0;i<12;i++){                                 if(map[i][j]==1){                                         g.fillRect(i*10, j*10, 10, 10);                                 }                                 if(map[i][j]==2){                                         g.drawRect(i*10, j*10, 10, 10);                                 }                         }                 }                 g.drawString("score=" +score,125,10);                 g.drawString("level=" +level,125,30);                 g.drawString("抵制不良游戏,",125,50);                 g.drawString("拒绝盗版游戏。",125,70);                 g.drawString("注意自我保护,",125,90);                 g.drawString("谨防受骗上当。",125,110);                 g.drawString("适度游戏益脑,",125,130);                 g.drawString("沉迷游戏伤身。",125,150);                 g.drawString("合理安排时间,",125,170);                 g.drawString("享受健康生活。",125,190);         }         public void keyPressed(KeyEvent e){                 switch(e.getKeyCode()){                 case KeyEvent.VK_DOWN:                         down();                         break;                 case KeyEvent.VK_UP:                         turn();                         break;                 case KeyEvent.VK_RIGHT:                         right();                         break;                 case KeyEvent.VK_LEFT:                         left();                         break;                 }         }         public void keyReleased(KeyEvent e){         }         public void keyTyped(KeyEvent e){         }         class TimerListener implements ActionListener{                 public void actionPerformed(ActionEvent e){                         repaint();                         if(blow(x,y+1,blockType,turnState)==1){                                 y=y+1;                                 delline();                         }                         ;                         if(blow(x,y+1,blockType,turnState)==0){                                 if(flag==1){                                         add(x,y,blockType,turnState);                                         delline();                                         newblock();                                         flag=0;                                 }                                 flag=1;                         }                         ;                 }         } }