我正在用 Java 构建俄罗斯方 block ,作为一个有趣的业余项目,现在正在致力于轮换。
我最初对每个旋转进行硬编码,这被证明是相当乏味的。
话虽如此,我当时打算尝试使用线性代数进行矩阵旋转,但是 Mathematics.SE 上有人建议我尝试转置。因此,根据他的描述,我尝试将其绘制出来。我的图纸正确吗?
从此,我不再尝试编写转置代码,但现在完全迷失在我的代码中。
public void getTranspose() {
Tile[][] gridTranspose = transpose();
System.out.println();
System.out.println("B`:");
for (int j = 0; j < gridTranspose.length; j++) {
for (int i = 0; i < gridTranspose[j].length-1; i++) {
System.out.print("(" + i + ", " + j + ") ");
}
System.out.println();
}
}
public Tile[][] transpose() {
Tile gridT[][];
gridT = new Tile[width][height];
System.out.println("B:");
for(int i = 0; i < grid.length; i++) {
for(int j = 0; j < grid[i].length-1; j++) {
System.out.print("(" + i + ", " + j + ") ");
gridT[j][i] = grid[i][j];
}
System.out.println();
}
return gridT;
}
这输出了一个看似正确的转置图?
B:
(0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8)
(1, 0) (1, 1) (1, 2) (1, 3) (1, 4) (1, 5) (1, 6) (1, 7) (1, 8)
(2, 0) (2, 1) (2, 2) (2, 3) (2, 4) (2, 5) (2, 6) (2, 7) (2, 8)
(3, 0) (3, 1) (3, 2) (3, 3) (3, 4) (3, 5) (3, 6) (3, 7) (3, 8)
(4, 0) (4, 1) (4, 2) (4, 3) (4, 4) (4, 5) (4, 6) (4, 7) (4, 8)
(5, 0) (5, 1) (5, 2) (5, 3) (5, 4) (5, 5) (5, 6) (5, 7) (5, 8)
(6, 0) (6, 1) (6, 2) (6, 3) (6, 4) (6, 5) (6, 6) (6, 7) (6, 8)
(7, 0) (7, 1) (7, 2) (7, 3) (7, 4) (7, 5) (7, 6) (7, 7) (7, 8)
(8, 0) (8, 1) (8, 2) (8, 3) (8, 4) (8, 5) (8, 6) (8, 7) (8, 8)
(9, 0) (9, 1) (9, 2) (9, 3) (9, 4) (9, 5) (9, 6) (9, 7) (9, 8)
B`:
(0, 0) (1, 0) (2, 0) (3, 0) (4, 0) (5, 0) (6, 0) (7, 0) (8, 0)
(0, 1) (1, 1) (2, 1) (3, 1) (4, 1) (5, 1) (6, 1) (7, 1) (8, 1)
(0, 2) (1, 2) (2, 2) (3, 2) (4, 2) (5, 2) (6, 2) (7, 2) (8, 2)
(0, 3) (1, 3) (2, 3) (3, 3) (4, 3) (5, 3) (6, 3) (7, 3) (8, 3)
(0, 4) (1, 4) (2, 4) (3, 4) (4, 4) (5, 4) (6, 4) (7, 4) (8, 4)
(0, 5) (1, 5) (2, 5) (3, 5) (4, 5) (5, 5) (6, 5) (7, 5) (8, 5)
(0, 6) (1, 6) (2, 6) (3, 6) (4, 6) (5, 6) (6, 6) (7, 6) (8, 6)
(0, 7) (1, 7) (2, 7) (3, 7) (4, 7) (5, 7) (6, 7) (7, 7) (8, 7)
(0, 8) (1, 8) (2, 8) (3, 8) (4, 8) (5, 8) (6, 8) (7, 8) (8, 8)
(0, 9) (1, 9) (2, 9) (3, 9) (4, 9) (5, 9) (6, 9) (7, 9) (8, 9)
所以我的问题是:
1)我上面的图是对其描述的正确解释吗?
2) 我是否正确生成了转置图?
3)如果是这样,我应该如何绘制旋转的 block ...我应该用 transpose()
替换 grid[row][col]
吗?
public void paintComponent(Graphics g) {
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
for(int row = 0; row < grid.length; row++) {
for(int col = 0; col < grid[row].length; col++) {
if(grid[row][col] != null) {
//if there is a non-null space, that is a Tetris piece.. fill it red
if (grid[row][col].getColor() != null) {
g.setColor(grid[row][col].getColor());
g.fillRect(row * tilesize, col * tilesize, tilesize, tilesize);
g.setColor(Color.WHITE);
g.drawString("(" + row + ", " + col + ")", row * tilesize, col * tilesize+10);
}
}
}
}
}
谢谢!
最佳答案
单独移调并不适用于所有正常的俄罗斯方 block 。例如,以如下形状为例:
xx_
_xx
___
当你转置它时,你最终会得到这样的结果:
x__
xx_
_x_
因此,不要考虑某个特定的部分,而是考虑一下当您使用带有标记的角的正方形时会发生什么:
a_b
___
d_c
这可以非常清楚地表明您的轮换是否良好。那么让我们看看转置:
a_d
___
b_c
为了获得顺时针旋转,我们可以将其横向翻转:
d_a
___
c_b
再次执行相同的操作应该会让我们从开始的地方旋转整整一半。进行转置:
d_c
___
a_b
然后翻转它:
c_d
___
b_a
因此,为了进行顺时针旋转,只需进行转置并翻转即可。如果我们做相反的事情,翻转它然后进行转置,会发生什么?从之前的方向开始,如果我们翻转它,我们会得到以下结果:
d_c
___
a_b
现在进行转置:
d_a
___
c_b
我们又回到了旋转一圈后的状态 - 逆时针旋转。因此,单独移调是行不通的,但移调与水平翻转相结合可以满足您的所有需求!
至于你的问题,
我不确定您的绘图是否正确。根据您留下的评论,我怀疑我可能误解了它们,这就是为什么我制作了上面的图来显示需要发生的情况。
是的,这是一个正确转置的图表。您可能不想在循环中使用
gridTranspose[j].length-1
,因为这会切断一列。要绘制旋转的 block ,我建议使用一个单独的变量来保存当前 block 。如果该 block 位于
x,y
处,那么您可以在paintComponent
方法中添加如下内容:for(int row = 0; row < piece.length(); row++) { for(int col = 0; col < piece.width(); piece++) { if(piece.hasBlockAt(row, col) { g.setColor(piece.getColorAt(row, col)); g.fillRect((row+x) * tilesize, (col+y) * tilesize, tilesize, tilesize); } } }
关于Java Tetris - 使用转置来旋转一 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16090855/