user3871
user3871

Reputation: 12718

Java Tetris - Using transpose to rotate a piece

I'm building Tetris in Java as a fun side project and am now working on rotations.

I was originally hard coding each rotation which was proving to be quite tedious.

That being said, I was then going to try Matrix Rotations using linear algebra, but someone on the Mathematics.SE recommended I try transposing. So given his description, I tried drawing it out. Did I get the drawings correct?

enter image description here

From that, I'm not trying to code the transpose, but now am completely lost in my code.

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;   
}

This outputs a seemingly correct transposed graph?

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) 

So my questions are:

1) Is my drawing above a correct interpretation of his description?

2) Am I correctly generating a transposed graph?

3) If so, how should I paint the rotated block... Should I just replace grid[row][col] with transpose()?

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);
                }           
            }
        }
    }
}

Thanks!

Upvotes: 2

Views: 1353

Answers (1)

Rob Watts
Rob Watts

Reputation: 7146

Transposing alone won't work for all of the normal tetris pieces. For example, take the piece shaped like this:

xx_
_xx
___

When you transpose it, you end up with this:

x__
xx_
_x_

So rather than think about a particular piece, think about what happens when you work with a square with the corners labeled:

a_b
___
d_c

This make it very clear if your rotation is good or not. So let's look at transpose:

a_d
___
b_c

In order to get the clockwise rotation, we can just flip it sideways:

d_a
___
c_b

Performing the same operation again should give us a full half rotation from where we started. Take the transpose:

d_c
___
a_b

And flip it:

c_d
___
b_a

So in order to do a clockwise rotation, simply take the transpose and flip it. What happens if we do the opposite, flip it and then take the transpose? Working from the previous orientation, this is what we get if we flip it:

d_c
___
a_b

Now take the transpose:

d_a
___
c_b

And we're back to what we had after one rotate - a counterclockwise rotation. So transposing alone won't work, but transposing combined with a horizontal flip does everything you need!

As for your questions,

  1. I'm not sure your drawing is a correct interpretation. Based on the comments you left I suspect that I may have misunderstood them, which is why I made the drawings above to show what needs to happen.

  2. Yes, that is a correctly transposed graph. You probably don't want to use gridTranspose[j].length-1 in the loops, as that cuts off one column.

  3. To paint the rotated block, I would suggest having a separate variable for holding the current piece. If the piece were at x,y, then you would put something like this in your paintComponent method:

    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);
            }
        } 
    } 
    

Upvotes: 3

Related Questions