2009-03-14 34 views
17

Estoy programando un clon de Tetris y en mi juego guardo mis bloques de tetromino como matrices de bloques de 4x4. Ahora necesito poder rotar las posiciones enteras en las matrices para obtener un bloque de tetris girado. No puedo simplemente rotar la textura porque toda mi detección de colisiones, etc., ha sido diseñada para trabajar con la matriz 2D. El juego está escrito en C# usando XNA.Cómo rotar una matriz 2D de enteros

¿Cómo puedo rotar mi matriz 2D de entradas 90 grados en sentido horario/antihorario?

Así es como mi bloque 'L' se almacena como un ejemplo.

0 1 0 0 
0 1 0 0 
0 1 1 0 
0 0 0 0 

Gracias por su ayuda.

+0

C# y C++? –

Respuesta

29

Si se trata de una matriz 2D, puede implementar la rotación copiando con diferentes órdenes de acceso a la matriz.

es decir, para una rotación en sentido horario, Probar:

int [,] newArray = new int[4,4]; 

for (int i=3;i>=0;--i) 
{ 
    for (int j=0;j<4;++j) 
    { 
     newArray[j,3-i] = array[i,j]; 
    } 
} 

Counter-agujas del reloj es similar.

+0

Buena solución, pero excesiva dado el dominio del problema. –

+0

probando este código ahora ... –

+0

Voto esto, debería marcarse como la solución. No estoy seguro de lo que quiere decir rde6173, a menos que también esté garantizando el almacenamiento de 4 matrices de orientación. – Ricket

4

Si desea girar un bloque de 4 x 4, sólo hay que mover las posiciones:

A B C A 
C D D B 
B D D C 
A C B A 

Cada A se mueve a la siguiente A, y lo mismo para B, C y D.

/-----\ 
    |  | 
    |  V 
    A B C A 
/->C D>D B--\ 
| B D D C | 
| A C B A | 
| |^ | 
| | | | 
\----/ \----/  
+0

Creo que su imagen está un poco apagada, no estoy seguro exactamente de qué está tratando de aclararlo y las flechas parecen apuntar b -> cy a -> c en lugar de apoyar sus instrucciones. fmsf, crecer. – Ricket

+0

@Ricket gracias, lo corrigió. –

6

En tetris clásicos hay muy pocas permutaciones de objetos. Simplemente tendría una matriz constante para cada "tetromino" en cada una de las 4 posiciones, y una lógica simple para elegir la adecuada en función de la entrada.

¿Por qué perder ciclos de CPU al intentar rotarlo?

+0

La matemática es tan simple en este caso, es tan rápido como rotarla como lo haría con la búsqueda de permutación basada en el estilo de bloque actual + posición. –

+0

Eso es ridículo. –

+0

También agregaría que desde un punto de vista de juego y diseño, podría ser mejor tener rotaciones preestablecidas. ¿Qué haces cuando obtienes la pieza larga de 4x1? Si lo gira dos veces, ¿debería estar realmente un espacio completo hacia el costado (lo que sería si usa matemática pura)? –

11

No gire las piezas con el código. Simplemente almacene una matriz de las diferentes orientaciones de las piezas y cítalas cuando la pieza gire. No es necesario rotarlos dinámicamente en un juego Tetris.

Como el dominio del problema es Tetris, encontrará que un algoritmo de rotación causa efectos no deseados, como el Tetrónomo largo y delgado que no alterna entre dos posiciones (como lo hace en el caso real).

+0

-1; No hay ninguna ventaja de almacenar 4 orientaciones de cada pieza en lugar de simplemente girar. Debería concentrarse en responder a su pregunta, no desalentarlo, a menos que esté cometiendo un error grave; que ciertamente no es – Ricket

+0

Me tomaría mucho menos tiempo escribir un doble para el ciclo como se sugirió anteriormente. –

+4

Ricket, fácil en el tono allí. He actualizado mi respuesta para indicar por qué la rotación es una mala idea en este caso. – Jon

1

Guardaría (x, y) las coordenadas de las "celdas" y usaría la matriz de rotación para rotarlas. Véase Drawing a Rotated Rectangle por ejemplo. Probablemente tenga que redondear el resultado al incremento de 0.5 más cercano. código

0

js tanto en sentido horario y antihorario:

function arrRotation90(arr, clockwise) { 
      var arr_rotated = []; 
      for (var i = 0; i < arr[0].length; i++) { 
       arr_rotated[i] = []; 
      } 
      if (clockwise) { 
       for (var i = 0; i < arr.length; i++) { 
        for (var j = 0; j < arr[i].length; j++) { 
         arr_rotated[arr[i].length-1-j][i] = arr[i][j]; 
        } 
       } 
      } else { 
       for (var i = 0; i < arr.length; i++) { 
        for (var j = 0; j < arr[i].length; j++) { 
         arr_rotated[j][arr.length - 1 - i] = arr[i][j]; 
        } 
       } 
      } 
      return arr_rotated; 
     }