2011-03-31 144 views
3

我知道这已被问了很多,但我想知道如何旋转俄罗斯方块片? 我已经做了一个漫长而糟糕的解决方案(约170行代码),但应该有更简单的方法来做到这一点。爪哇俄罗斯方块轮换

我的俄罗斯方块片由4个块组成,它们都知道它们在矩阵中的位置(行和列)。矩阵本身是字符型的,所以4个块都是字母。它看起来像这样的例子:

...... 
..T... 
.TTT.. 
...... 

我试图模仿我的矩阵通过计算中间的行和列,并使用它作为一个ORIGO,然后根据坐标系尝试应用这种简单的算法,我发现: 90度旋转(x,y)=(-y,x)

它似乎只在我的棋子位于矩阵的中心时才起作用。我不知道该怎么做,我一整天都在想这个。这里是我的方法:

public void rotatePiece(ArrayList<Block> random) { 
     int distance = 0; // how far is the origo 

     for (int i=0; i < 4; ++i) 
      board[random.get(i).getRow()][random.get(i).getColumn()] = '.'; // erases the current location of the piece 

     for (int i=0; i < 4; ++i) { 
      distance = Math.abs(random.get(i).getColumn()-middleColumn); 

      if (random.get(i).getColumn() < middleColumn) 
       random.get(i).setColumn(random.get(i).getColumn()+(distance*2)); // "throws" the location of the block to the other side of the origo 
      else 
       random.get(i).setColumn(random.get(i).getColumn()-(distance*2)); 

      int help = random.get(i).getColumn(); 
      random.get(i).setColumn(random.get(i).getRow()); // (x, y) = (-y, x) 
      random.get(i).setRow(help); 
     } 

     for (int i=0; i < 4; ++i) 
      board[random.get(i).getRow()][random.get(i).getColumn()] = random.get(0).getStyle(); // saves the new location of the piece in the matrix 

回答

1

可以使用rotation matrix

您将需要适当地设置您的旋转的原点,这可能意味着相对于运动场平移了棋子的位置(例如,原点位于中心),应用旋转矩阵和然后将其翻译回其在运动场坐标上的正确位置。

+0

你能在此解释一下?你能提供一个示例实现吗? – Growler 2013-04-08 16:49:16

1

要做到这一点,最简单和计算最快的方法是使用预先计算它们。

这意味着俄罗斯方块一块看起来像

class TetrisBlock { 

    String position[4]; 

    int curPos = 0; 

    void rotateLeft() { 
     curPos++; 
     if (curPos > 3) 
     curPos = 0; 
    } 
.... 
} 

然后你可以定义类似

class TetrisTBlock extends TetrisBlock { 

... 

// in constructor 
position={"....\n.T..\nTTT.\n....", 
      ".T..\nTT..\n.T..\n.....", 
// I guess you get the idea 

...

您为每个类型的块,然后做这个您还可以添加成员以添加/删除它们。

如果你优化你会去从字符远....

2

我会建议定义每个块组四个州。

enum ROTATION { 
    UP, DOWN, LEFT, RIGHT; 

    ROTATION rotateLeft() { 
     switch(this) { 
      case UP: return LEFT; 
      case LEFT: return DOWN; 
      case DOWN: return RIGHT; 
      case RIGHT: return UP; 
     } 
     return null; // wont happen; 
    } 

    ROTATION rotateRight() { 
     ROTATION r = this; 
     // wow I'm lazy, but I've actually seen this in production code! 
     return r.rotateLeft().rotateLeft().rotateLeft(); 
    } 
} 

abstract class Brick { 
    Point centerPos; 
    ROTATION rot; 
    abstract List<Point> pointsOccupied(); 
} 

class TBrick extends Brick { 

    List<Point> pointsOccupied() { 
     int x = centerPos.x(); 
     int y = centerPos.y(); 
     List<Point> points = new LinkedList<Point>(); 
     switch(rot) { 
      case UP: points.add(new Point(x-1,y); 
        points.add(new Point(x,y); 
        points.add(new Point(x+1,y); 
        points.add(new Point(x, y+1); 
       break; 
      case Down: points.add(new Point(x-1,y); 
         points.add(new Point(x,y); 
         points.add(new Point(x+1,y); 
         points.add(new Point(x, y-1); 
       break; 
      // finish the cases 
     } 

    } 

} 
0

我认为最好的方法是硬编码它。考虑到每个数字都不同,并且每个数字的旋转阶段也不同。并且对于每个旋转阶段 - 确定您需要释放哪些网格部分(避免碰撞)。 有关视觉表现的检查this