J2ME实战:蓝牙联网俄罗斯方块(3)—方块生成与坐标控制模块

来源:互联网 发布:apache httpd.exe闪退 编辑:程序博客网 时间:2024/05/16 14:47

引言:这几天我由于生病,影响了写代码的进度,十分遗憾!好了,我会接住上一篇的继续写下去,希望和我一样不顾一切喜欢、热爱软件和游戏开发的朋友们继续支持我,你们的回帖就是对我最大的支持,要说明的是:如果发现文章或代码中的错误之处请指出,欢迎所有阅读这篇文章的人,我们一起进步,一起提高!

 

步入正题:这篇讲的是方块生成与坐标控制模块TetrisBlock类。

 

在TetrisBlock类中定义了7种方块的不同形状和对应的颜色,都有一个对应的ID,分别为1—7,且对于每种方块来说,其颜色均是固定,方块由16个4*4的小方格组成,故在逻辑上可以使用4*4的二维数组表示,又由于每个方块都有4种旋转变化,故可以用4*4*4的三维数组表示一个方块的所有状态。

 

例如,“T”形方块可由如下的数组来表示:

 

 

Java代码 复制代码
  1. protected int blockpattern1[][][]={//blockpattern1:“T”字及四种旋转形状   
  2.      {{0,0,0,0},{1,1,1,0},{0,1,0,0},{0,0,0,0}},   
  3.         {{0,1,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}},   
  4.         {{0,1,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},   
  5.         {{0,1,0,0},{0,1,1,0},{0,1,0,0},{0,0,0,0}}      
  6.     };  

 

小tips:这一章代码是俄罗斯方块生成与控制算法,应该是比较重要的,所以我的注释写得尽可能的多,希望所有的人都能看得明白!

 

1.方块生成与坐标控制模块(TetrisBlock类)

程序源代码如下:

 

Java代码 复制代码
  1. /*  
  2.  * To change this template, choose Tools | Templates  
  3.  * and open the template in the editor.  
  4.  */  
  5.   
  6. package game.teris;   
  7.   
  8. import java.util.Random;   
  9. import javax.microedition.lcdui.Graphics;   
  10.   
  11. /**  
  12.  *  
  13.  * @author dongdong  
  14.  */  
  15. public class TetrisBlock {   
  16.   
  17.     //各种方块,1-7为活动方块的颜色,8为砖墙的颜色   
  18.     public static final int[] BRICK_COLORS = {   
  19.         0x00FF0000,   
  20.         0x0000FF00,   
  21.         0x00FFFF00,   
  22.         0x000000FF,   
  23.         0x00FF00FF,   
  24.         0x0000FFFF,   
  25.         0x00C0DCC0,   
  26.         0x00808080  
  27.     };   
  28.     /**  
  29.      * blockpattern的编码规则:blockpattern表示一种方块的形状  
  30.      * 每种方块的颜色是固定的  
  31.      * 对于一个方块,用一个三维数组表示,第一维用rot表示(旋转值),第二维用  
  32.      * x表示(行),第三维用y表示(列)  
  33.      * 第一维最重要即rot,表示旋转值  
  34.      */  
  35.     protected int blockpattern1[][][]={//blockpattern1:“T”字及四种旋转形状   
  36.         {{0,0,0,0},{1,1,1,0},{0,1,0,0},{0,0,0,0}},   
  37.         {{0,1,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}},   
  38.         {{0,1,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},   
  39.         {{0,1,0,0},{0,1,1,0},{0,1,0,0},{0,0,0,0}}      
  40.     };   
  41.     protected int blockpattern2[][][]={//blockpattern2:“田”字及四种旋转形状   
  42.         {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},   
  43.         {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},   
  44.         {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},   
  45.         {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}      
  46.     };   
  47.     protected int blockpattern3[][][]={//blockpattern3:“L”字及四种旋转形状   
  48.         {{1,1,0,0},{0,1,0,0},{0,1,0,0},{0,0,0,0}},   
  49.         {{0,0,1,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}},   
  50.         {{1,0,0,0},{1,0,0,0},{1,1,0,0},{0,0,0,0}},   
  51.         {{1,1,1,0},{1,0,0,0},{0,0,0,0},{0,0,0,0}}      
  52.     };   
  53.     protected int blockpattern4[][][]={//blockpattern4:反“L”字及四种旋转形状   
  54.         {{1,1,0,0},{1,0,0,0},{1,0,0,0},{0,0,0,0}},   
  55.         {{1,1,1,0},{0,0,1,0},{0,0,0,0},{0,0,0,0}},   
  56.         {{0,1,0,0},{0,1,0,0},{1,1,0,0},{0,0,0,0}},   
  57.         {{1,0,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}}      
  58.     };   
  59.     protected int blockpattern5[][][]={//blockpattern5:反“Z”字及四种旋转形状   
  60.         {{1,0,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}},   
  61.         {{0,1,1,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},   
  62.         {{1,0,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}},   
  63.         {{0,1,1,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}      
  64.     };   
  65.     protected int blockpattern6[][][]={//blockpattern6:“Z”字及四种旋转形状   
  66.         {{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}},   
  67.         {{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}},   
  68.         {{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}},   
  69.         {{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}}      
  70.     };   
  71.     protected int blockpattern7[][][]={//blockpattern7:“1”字及四种旋转形状   
  72.         {{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},   
  73.         {{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}},   
  74.         {{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},   
  75.         {{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}}      
  76.     };   
  77.        
  78.     /*当前下坠方块形状,为以上定义的7种方块之一*/  
  79.     private int blockpattern[][][];   
  80.        
  81.     /*下一个方块形状,显示在游戏容器的右边*/  
  82.     private int blockNextpattern[][][];   
  83.        
  84.     //blockpattern左上角x坐标   
  85.     //x=i表示左上角距离游戏容器左上角x轴上i个小砖块单位   
  86.     private int x;   
  87.        
  88.     //blockpattern左上角y坐标   
  89.     //y=i表示左上角距离游戏容器左上角y轴上i个小砖块单位   
  90.     private int y;   
  91.        
  92.     //x的旧值   
  93.     private int oldx;   
  94.        
  95.     //y的旧值   
  96.     private int oldy;   
  97.        
  98.     //旋转值,0-3   
  99.     private int rot;   
  100.        
  101.     //旋转旧值   
  102.     private int oldrot;   
  103.        
  104.     /*当前下坠方块*/  
  105.     private int pattern;   
  106.        
  107.     /*下一个下坠方块*/  
  108.     private int next;   
  109.        
  110.     private final int UNDEFINED=99;   
  111.        
  112.     private TetrisMap map;   
  113.     protected Random rand;   
  114.        
  115.     public int gamearea_x;   
  116.     public int gamearea_y;   
  117.     public int brick_Width;   
  118.        
  119.     /*构造函数,保存map,初始化blockimage、rand、next*/  
  120.     public TetrisBlock(TetrisMap map,boolean isMaster){   
  121.         this.map=map;   
  122.         if(isMaster){   
  123.             rand= new Random();   
  124.             //随机生成的pattern和next在1-7之间,8为墙   
  125.             next=Math.abs(rand.nextInt())%7+1;   
  126.             pattern=next;   
  127.             next=Math.abs(rand.nextInt())%7+1;    
  128.         }   
  129.         else{   
  130.             //如果本TetrisBlock代表的是附屏   
  131.             //则当前下坠方块和下一个下坠方块由远端设备决定   
  132.             pattern=UNDEFINED;   
  133.             next=UNDEFINED;   
  134.         }   
  135.         setParameter();   
  136.     }   
  137.     /**  
  138.      * 用来设置附屏对应的TetrisBlock对象  
  139.      * @param pattern_2  
  140.      * @param next_2  
  141.      */  
  142.     public void setPN(int pattern_2,int next_2){   
  143.         pattern=pattern_2;   
  144.         next=next_2;   
  145.     }   
  146.        
  147.     public void setParameter(){   
  148.         gamearea_x=map.gamearea_x;   
  149.         gamearea_y=map.gamearea_y;   
  150.         brick_Width=map.brick_Width;   
  151.     }   
  152.        
  153.     /*初始化*/  
  154.     protected void init(){   
  155.            
  156.     }   
  157.        
  158.     /**  
  159.      * 读取当前下坠方块  
  160.      * @param nowblock int[][][] 七种方块常量之一  
  161.      */  
  162.     private void readPattern(int[][][] nowblock){   
  163.         blockpattern=new int[4][4][4];   
  164.         for(int i=0;i<4;i++){   
  165.             for(int j=0;j<4;j++){   
  166.                 for(int k=0;k<4;k++){   
  167.                     blockpattern[i][j][k]=nowblock[i][j][k];   
  168.                 }   
  169.             }   
  170.         }   
  171.     }   
  172.        
  173.     /**  
  174.      * 读取下一个下坠方块  
  175.      * 只需要保存4种旋转变化中的第一种即可,所以rot=0  
  176.      * @param nowblock int[][][] 7种方块之一  
  177.      */  
  178.     private void readNextPattern(int[][][] nowblock){   
  179.         blockNextpattern=new int[0][4][4];   
  180.         for(int i=0;i<4;i++){   
  181.             for(int j=0;j<4;j++){   
  182.                 blockNextpattern[0][i][j]=nowblock[0][i][j];   
  183.             }   
  184.         }   
  185.     }   
  186.        
  187.     /*旋转方块*/  
  188.     protected void rotBlock(){   
  189.            
  190.     }   
  191.        
  192.     /**  
  193.      * 绘制方块,包括清除下坠方块的旧图像,调用绘制下坠方块新图像  
  194.      * 本地方法  
  195.      * @param g Graphics  
  196.      */  
  197.     public void paint(Graphics g){   
  198.         //如果三维都没有变化,则无需重画   
  199.         if( (oldrot!=rot)||(oldx!=x)||(oldy!=y) ){   
  200.             //清除旧图形   
  201.             g.setColor(TetrisCanvas.BACKGROUND);   
  202.             for(int i=0;i<4;i++){   
  203.                 for(int j=0;j<4;j++){   
  204.                     if(blockpattern[oldrot][i][j] == 1){   
  205.                         g.fillRect(gamearea_x +   
  206.                                 (oldx + j) * brick_Width,   
  207.                                 gamearea_y +   
  208.                                 (oldy + i) * brick_Width,   
  209.                                 brick_Width, brick_Width);   
  210.                     }   
  211.                 }   
  212.             }   
  213.             drawBlock(g);   
  214.             oldrot=rot;   
  215.             oldx=x;   
  216.             oldy=y;   
  217.         }   
  218.     }   
  219.        
  220.     /**  
  221.      * 绘制下坠方块  
  222.      * @param g Graphics  
  223.      * 本地、远端均可使用  
  224.      */  
  225.     public void drawBlock(Graphics g){   
  226.         for(int i=0;i<4;i++){   
  227.             for(int j=0;j<4;j++){   
  228.                 if(blockpattern[rot][i][j] == 1){   
  229.                   drawBrick(gamearea_x +   
  230.                           (x + j) * brick_Width,   
  231.                           gamearea_y +    
  232.                           (y + i) * brick_Width,g,pattern - 1);     
  233.                 }   
  234.             }   
  235.         }   
  236.     }   
  237.        
  238.     /**  
  239.      * 远端用户使用、清除当前下坠的方块  
  240.      */  
  241.     public void eraseBlock(Graphics g){   
  242.            
  243.     }   
  244.        
  245.     /**  
  246.      * 判断下坠方块是不是和map种已有的砖块重叠,为了处理gameover的情况,只需画出部分  
  247.      * 下坠方块的情况  
  248.      * @return true:有重叠;false:无重叠  
  249.      */  
  250.     public boolean isCrashAtBegin(){   
  251.         //行   
  252.         for(int i=3;i>=0;i--){   
  253.             //列   
  254.             for(int j=0;j<4;j++){   
  255.                 int mx=x + j;   
  256.                    
  257.                 int my=y + i;   
  258.                 if(my<0){   
  259.                     my=0;   
  260.                 }   
  261.                    
  262.                 if(blockpattern[rot][i][j] == 1 && map.get(mx, my) != 8 &&   
  263.                         map.get(mx, my) != 0){   
  264.                     return true;   
  265.                 }   
  266.             }   
  267.         }   
  268.         return false;   
  269.     }   
  270.        
  271.     /**  
  272.      * 画小砖块  
  273.      * @param px x坐标  
  274.      * @param py y坐标  
  275.      * @param g Graphics  
  276.      * @param colorIndex颜色索引值  
  277.      */  
  278.     public void drawBrick(int px, int py, Graphics g, int colorIndex){   
  279.         //画白边   
  280.         g.setColor(255255255);   
  281.         g.fillRect(px, py, 1, brick_Width);   
  282.         g.fillRect(px, py, brick_Width, 1);   
  283.         //画中心   
  284.         int color=BRICK_COLORS[colorIndex];   
  285.         g.setColor(color);   
  286.         g.fillRect(px+1, py+1, brick_Width-1,   
  287.                 brick_Width-1);   
  288.         //画灰边   
  289.         g.setColor(0x00c0c0c0);   
  290.         g.fillRect(px + brick_Width - 1, py + 11,    
  291.                 brick_Width - 1);   
  292.         g.fillRect(px + 1, py + brick_Width - 1,    
  293.                 brick_Width - 21);   
  294.     }   
  295.        
  296.     /**  
  297.      * 在游戏容器的右边绘出下一个下坠物形状  
  298.      * @param g Graphics  
  299.      */  
  300.     public void drawNextBlock(Graphics g){   
  301.            
  302.     }   
  303.        
  304.     /**  
  305.      * 判断下坠方块是否能下移  
  306.      */  
  307.     public boolean checkDown(){   
  308.            
  309.         boolean check = true;   
  310.         /*分别扫描下坠物的4行,从最下面的那行开始*/  
  311.         for(int i = 0;i < 4;i++){   
  312.             int row=3;   
  313.             while(row >= 0){   
  314.                 if(blockpattern[rot][row][i] == 1){   
  315.                     if(map.get(x + i, y + row + 1) !=0){   
  316.                         check = false;   
  317.                     }   
  318.                     row = -1//终止循环   
  319.                 }   
  320.                 else{   
  321.                     row--;   
  322.                 }   
  323.             }   
  324.         }   
  325.         return check;   
  326.     }   
  327.        
  328.     /*下坠物下移1行*/  
  329.     public void down(){   
  330.            
  331.     }   
  332.        
  333.     /*判断是否能旋转*/  
  334.     public boolean checkRot(){   
  335.            
  336.         boolean check = true;   
  337.            
  338.         int tmpRot = rot + 1;   
  339.         if(tmpRot == 4){   
  340.             tmpRot = 0;   
  341.         }   
  342.            
  343.         for(int i = 0; i < 4; i++){   
  344.             for(int j = 0; j < 4; j++){   
  345.                 if(blockpattern[tmpRot][i][j] == 1){   
  346.                     if(map.get(x + j, y + i) != 0){   
  347.                         check = false;   
  348.                     }   
  349.                 }   
  350.             }   
  351.         }   
  352.            
  353.         return check;   
  354.     }   
  355.        
  356.     /*判断下坠物是否可以移动*/  
  357.     public boolean checkMove(int direct){   
  358.            
  359.         boolean check = true;   
  360.         //分别扫描下坠物的4行   
  361.         for(int i = 0; i < 4; i++){   
  362.             if(direct == 1){ //左移   
  363.                 int row = 0;   
  364.                 while(row <= 3){   
  365.                     if(blockpattern[rot][i][row] == 1){   
  366.                         if(map.get(x + row - 1, y + i) != 0){   
  367.                             check = false;   
  368.                         }   
  369.                         row = 4;//终止循环   
  370.                     }   
  371.                     else{   
  372.                         row++;   
  373.                     }   
  374.                 }   
  375.             }   
  376.             else//右移   
  377.                 int row = 3;   
  378.                 while(row >= 0){   
  379.                     if(blockpattern[rot][i][row] == 1){   
  380.                         if(map.get(x + row +1, y + i) != 0){   
  381.                             check = false;   
  382.                         }   
  383.                         row = -1//终止循环   
  384.                     }   
  385.                     else{   
  386.                         row--;   
  387.                     }   
  388.                 }   
  389.             }   
  390.         }   
  391.         return check;   
  392.     }   
  393.        
  394.     /*左右移动*/  
  395.     public void move(int direct){   
  396.            
  397.     }   
  398.     public int getY(){   
  399.            
  400.     }   
  401.        
  402.     /**  
  403.      * 根据下坠物的当前位置设置地图数据  
  404.      */  
  405.     public void fixBlock(){   
  406.            
  407.     }   
  408.        
  409.     public int getPattern(){   
  410.            
  411.     }   
  412.        
  413.     public int getNext(){   
  414.            
  415.     }   
  416.        
  417.     /**  
  418.      * 空中的方块落下后,则产生新的方块  
  419.      */  
  420.     public void generatePN(){   
  421.         pattern=next;   
  422.         next=Math.abs(rand.nextInt())%7+1;   
  423.     }   
  424. }