最终效果图:

 

 

核心实现代码:

 

  1. /** 
  2.  *  
  3.  * @author charles.wang 
  4.  * @created Apr 12, 2011 7:07:19 PM 
  5.  * Description:创建一个俄罗斯方块类 
  6.  */ 
  7. public class RussiaBlock extends JPanel implements KeyListener { 
  8.  
  9.      
  10.      
  11.  
  12.     private int blockType; // blockType 代表方块类型 
  13.  
  14.     private int score = 0
  15.  
  16.     private int turnState; // turnState代表方块状态 
  17.  
  18.     private int x; 
  19.  
  20.     private int y; 
  21.  
  22.     private int i = 0
  23.  
  24.     int j = 0
  25.  
  26.     int flag = 0
  27.  
  28.     // 定义已经放下的方块x=0-11,y=0-21; 
  29.  
  30.     int[][] map = new int[13][23]; 
  31.  
  32.     // 方块的形状 第一组代表方块类型有S、Z、L、J、I、O、T 7种 第二组 代表旋转几次 第三四组为 方块矩阵 
  33.  
  34.     private final int shapes[][][] = new int[][][] { 
  35.             // i 
  36.             { { 0000111100000000 },  
  37.               { 0100010001000100 }, 
  38.               { 0000111100000000 }, 
  39.               { 0100010001000100 } }, 
  40.             // s 
  41.             { { 0110110000000000 },  
  42.               { 1000110001000000 }, 
  43.               { 0110110000000000 }, 
  44.               { 1000110001000000 } }, 
  45.             // z 
  46.             { { 1100011000000000 },  
  47.               { 0100110010000000 }, 
  48.               { 1100011000000000 }, 
  49.               { 0100110010000000 } }, 
  50.             // j 
  51.             { { 0100010011000000 }, 
  52.               { 1000111000000000 }, 
  53.               { 1100100010000000 }, 
  54.               { 1110001000000000 } }, 
  55.             // o 
  56.             { { 1100110000000000 },  
  57.               { 1100110000000000 }, 
  58.               { 1100110000000000 }, 
  59.               { 1100110000000000 } }, 
  60.             // l 
  61.             { { 1000100011000000 }, 
  62.               { 1110100000000000 }, 
  63.               { 1100010001000000 }, 
  64.               { 0010111000000000 } }, 
  65.             // t 
  66.             { { 0100111000000000 },  
  67.               { 0100110001000000 }, 
  68.               { 1110010000000000 }, 
  69.               { 0100011001000000 } } }; 
  70.  
  71.     // 生成新方块的方法,用随机数生成 
  72.  
  73.     public void newblock() { 
  74.         blockType = (int) (Math.random() * 1000) % 7
  75.         turnState = (int) (Math.random() * 1000) % 4
  76.         x = 4
  77.         y = 0
  78.         if (gameover(x, y) == 1) { 
  79.  
  80.             newmap(); 
  81.             drawwall(); 
  82.             score = 0
  83.             JOptionPane.showMessageDialog(null"GAME OVER"); 
  84.         } 
  85.     } 
  86.  
  87.     // 画围墙,不用我说了吧,就是方块的2个侧边和底边 
  88.  
  89.     public void drawwall() { 
  90.         for (i = 0; i < 12; i++) { 
  91.             //map[i][0] = 2; 
  92.             map[i][21]=2
  93.         } 
  94.         for (j = 0; j < 22; j++) { 
  95.             map[11][j] = 2
  96.             map[0][j] = 2
  97.         } 
  98.     } 
  99.  
  100.     // 初始化地图 
  101.  
  102.     public void newmap() { 
  103.         for (i = 0; i < 12; i++) { 
  104.             for (j = 0; j < 22; j++) { 
  105.                 map[i][j] = 0
  106.             } 
  107.         } 
  108.     } 
  109.  
  110.     // 初始化构造方法 
  111.     public RussiaBlock()  
  112.     { 
  113.         newblock();  //随机数生成当前方块 
  114.         newmap();    //初始化新地图 
  115.         drawwall();  //画方块的底边和侧边 
  116.         Timer timer = new Timer(1000new TimerListener()); //创建一个定时器 
  117.         timer.start(); 
  118.     } 
  119.  
  120.     // 旋转的方法 
  121.     // 其实更好的方案是利用状态机模式,用4个专门的类来代表4个状态,不过简单起见,我们这里就用简单变量表示 
  122.  
  123.     public void turn() { 
  124.         int tempturnState = turnState; 
  125.         turnState = (turnState + 1) % 4//+1后对4取模,来跳到下一个状态 
  126.         if (blow(x, y, blockType, turnState) == 1) { 
  127.         } 
  128.         if (blow(x, y, blockType, turnState) == 0) { 
  129.             turnState = tempturnState; 
  130.         } 
  131.         repaint(); 
  132.     } 
  133.  
  134.     // 左移的方法 
  135.     // 左移则起始横坐标少1 
  136.  
  137.     public void left() { 
  138.         if (blow(x - 1, y, blockType, turnState) == 1) { 
  139.             x = x - 1
  140.         } 
  141.         ; 
  142.         repaint(); 
  143.     } 
  144.  
  145.     // 右移的方法 
  146.  
  147.     public void right() { 
  148.         if (blow(x + 1, y, blockType, turnState) == 1) { 
  149.             x = x + 1
  150.         } 
  151.         ; 
  152.         repaint(); 
  153.     } 
  154.  
  155.     // 下落的方法 
  156.  
  157.     public void down() { 
  158.         if (blow(x, y + 1, blockType, turnState) == 1) { 
  159.             y = y + 1
  160.             delline(); 
  161.         } 
  162.         ; 
  163.         if (blow(x, y + 1, blockType, turnState) == 0) { 
  164.             add(x, y, blockType, turnState); 
  165.             newblock(); 
  166.             delline(); 
  167.         } 
  168.         ; 
  169.         repaint(); 
  170.     } 
  171.  
  172.     // 是否合法的方法 
  173.     // x,y 表示当前位置 
  174.     // blockType 表示方块类型 
  175.     // turnState 表示方块状态 
  176.     public int blow(int x, int y, int blockType, int turnState) { 
  177.         for (int a = 0; a < 4; a++) { 
  178.             for (int b = 0; b < 4; b++) { 
  179.                  
  180.                 //这个判断表示不合法, 
  181.                 if (((shapes[blockType][turnState][a * 4 + b] == 1) && (map[x + b + 1][y + a] == 1)) 
  182.                         || ((shapes[blockType][turnState][a * 4 + b] == 1) && (map[x + b + 1][y + a] == 2))) { 
  183.  
  184.                     return 0
  185.                 } 
  186.             } 
  187.         } 
  188.         return 1
  189.     } 
  190.  
  191.     // 消行的方法 
  192.  
  193.     public void delline() { 
  194.         int c = 0
  195.         for (int b = 0; b < 22; b++) { 
  196.             for (int a = 0; a < 12; a++) { 
  197.                  
  198.                 if (map[a][b] == 1) { 
  199.  
  200.                     c = c + 1
  201.                     if (c == 10) { 
  202.                         //分数累加10 
  203.                         score += 10
  204.                         //把整个除底层以外的行全部下移1格 
  205.                         for (int d = b; d > 0; d--) { 
  206.                             for (int e = 0; e < 11; e++) { 
  207.                                  
  208.                                 map[e][d] = map[e][d - 1]; 
  209.  
  210.                             } 
  211.                         } 
  212.                     } 
  213.                 } 
  214.             } 
  215.             c = 0
  216.         } 
  217.     } 
  218.  
  219.     // 判断你挂的方法 
  220.  
  221.     public int gameover(int x, int y) { 
  222.         if (blow(x, y, blockType, turnState) == 0) { 
  223.             return 1
  224.         } 
  225.         return 0
  226.     } 
  227.  
  228.     // 把当前添加map 
  229.  
  230.     public void add(int x, int y, int blockType, int turnState) { 
  231.         int j = 0
  232.         for (int a = 0; a < 4; a++) { 
  233.             for (int b = 0; b < 4; b++) { 
  234.                 if (map[x + b + 1][y + a] == 0) { 
  235.                     //填充目前位置 
  236.                     map[x + b + 1][y + a] = shapes[blockType][turnState][j]; 
  237.                 } 
  238.                 ; 
  239.                 j++; 
  240.             } 
  241.         } 
  242.     } 
  243.  
  244.     // 画方块的的方法 
  245.  
  246.     public void paintComponent(Graphics g) { 
  247.         super.paintComponent(g); 
  248.         // 画当前方块 
  249.  
  250.         for (j = 0; j < 16; j++) { 
  251.             if (shapes[blockType][turnState][j] == 1) { 
  252.                 g.fillRect((j % 4 + x + 1) * 10, (j / 4 + y) * 101010); 
  253.             } 
  254.         } 
  255.         // 画已经固定的方块 
  256.  
  257.         for (j = 0; j < 22; j++) { 
  258.             for (i = 0; i < 12; i++) { 
  259.                 if (map[i][j] == 1) { 
  260.                     g.fillRect(i * 10, j * 101010); 
  261.  
  262.                 } 
  263.                 if (map[i][j] == 2) { 
  264.                     g.drawRect(i * 10, j * 101010); 
  265.  
  266.                 } 
  267.             } 
  268.         } 
  269.         g.drawString("score=" + score, 12510); 
  270.         g.drawString("Kevin是老大,"12550); 
  271.         g.drawString("Sandro是小猪。"12570); 
  272.         g.drawString("Tony是牛人,"12590); 
  273.         g.drawString("Gabriel是探险家。"125110); 
  274.         g.drawString("Andrew是求知者,"125130); 
  275.         g.drawString("Eddy是小弟。"125150); 
  276.         g.drawString("Niki是外交家,"125170); 
  277.         g.drawString("Charles是打酱油的。"125190); 
  278.     } 
  279.  
  280.     // 键盘监听 
  281.     // 扑捉小键盘区的 上 下 左 右 键 
  282.     public void keyPressed(KeyEvent e) { 
  283.         switch (e.getKeyCode()) { 
  284.         case KeyEvent.VK_DOWN: 
  285.             down(); 
  286.             break
  287.         case KeyEvent.VK_UP: 
  288.             turn(); 
  289.             break
  290.         case KeyEvent.VK_RIGHT: 
  291.             right(); 
  292.             break
  293.         case KeyEvent.VK_LEFT: 
  294.             left(); 
  295.             break
  296.         } 
  297.  
  298.     } 
  299.  
  300.     // 无用 
  301.  
  302.     public void keyReleased(KeyEvent e) { 
  303.     } 
  304.  
  305.     // 无用 
  306.  
  307.     public void keyTyped(KeyEvent e) { 
  308.     } 
  309.  
  310.     // 定时器监听 
  311.  
  312.     class TimerListener implements ActionListener { 
  313.         public void actionPerformed(ActionEvent e) { 
  314.  
  315.             repaint(); 
  316.             if (blow(x, y + 1, blockType, turnState) == 1) { 
  317.                 y = y + 1
  318.                 delline(); 
  319.             } 
  320.             ; 
  321.             if (blow(x, y + 1, blockType, turnState) == 0) { 
  322.  
  323.                 if (flag == 1) { 
  324.                     add(x, y, blockType, turnState); 
  325.                     delline(); 
  326.                     newblock(); 
  327.                     flag = 0
  328.                 } 
  329.                 flag = 1
  330.             } 
  331.             ; 
  332.         } 
  333.     } 
  334.  

 

包装为Swing应用的封装代码:

 

  1. /** 
  2.  *  
  3.  * @author charles.wang 
  4.  * @created Apr 12, 2011 7:06:04 PM 
  5.  * Description: 俄罗斯方块测试类 
  6.  */ 
  7. public class RussiaBlockDemo extends JFrame { 
  8.     public RussiaBlockDemo() { 
  9.         RussiaBlock a = new RussiaBlock(); 
  10.         addKeyListener(a); 
  11.         add(a); 
  12.     } 
  13.  
  14.     public static void main(String[] args) { 
  15.         RussiaBlockDemo frame = new RussiaBlockDemo(); 
  16.         JMenuBar menu = new JMenuBar(); 
  17.         frame.setJMenuBar(menu); 
  18.         JMenu game = new JMenu("游戏"); 
  19.         JMenuItem newgame = game.add("新游戏"); 
  20.         JMenuItem pause = game.add("暂停"); 
  21.         JMenuItem goon = game.add("继续"); 
  22.         JMenuItem exit = game.add("退出"); 
  23.         JMenu help = new JMenu("帮助"); 
  24.         JMenuItem about = help.add("关于"); 
  25.         menu.add(game); 
  26.         menu.add(help); 
  27.         frame.setLocationRelativeTo(null); 
  28.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
  29.         frame.setSize(220275); 
  30.         frame.setTitle("无聊的公司-俄罗斯方块内测版"); 
  31.         // frame.setUndecorated(true); 
  32.         frame.setVisible(true); 
  33.         frame.setResizable(false); 
  34.  
  35.     }