Algorithm 俄罗斯方块旋转算法
代表和旋转俄罗斯方块游戏片段的最佳算法(和解释)是什么?我总是发现工件旋转和表示方案令人困惑 大多数俄罗斯方块游戏似乎在每次轮换时都会使用一种天真的“重制方块数组”: 但是,有些人使用预先构建的编码数字和位移位来表示每个片段:Algorithm 俄罗斯方块旋转算法,algorithm,rotation,tetris,Algorithm,Rotation,Tetris,代表和旋转俄罗斯方块游戏片段的最佳算法(和解释)是什么?我总是发现工件旋转和表示方案令人困惑 大多数俄罗斯方块游戏似乎在每次轮换时都会使用一种天真的“重制方块数组”: 但是,有些人使用预先构建的编码数字和位移位来表示每个片段: 有没有一种方法可以通过数学来实现这一点(不确定这种方法是否适用于基于单元的电路板)?形状数量有限,因此我会使用固定的表格,而不进行计算。这样可以节省时间 但也有旋转算法 选择一个中心点并旋转pi/2 如果一个块从(1,2)开始,它将顺时针移动到(2,-1)和(-1,-
有没有一种方法可以通过数学来实现这一点(不确定这种方法是否适用于基于单元的电路板)?形状数量有限,因此我会使用固定的表格,而不进行计算。这样可以节省时间 但也有旋转算法 选择一个中心点并旋转pi/2 如果一个块从(1,2)开始,它将顺时针移动到(2,-1)和(-1,-2)和(-1,2)。 将此应用于每个块,然后旋转工件 每个x都是前一个y,每个y都是前一个x。其中给出了以下矩阵:
[ 0 1 ]
[ -1 0 ]
对于逆时针旋转,请使用:
[ 0 -1 ]
[ 1 0 ]
我使用了一个形状位置和一组四个坐标来表示所有形状中的四个点。由于它位于二维空间中,因此可以轻松地将二维旋转矩阵应用于点
这些点是div,因此它们的css类从关闭变为打开。(这是在清除css类的上次旋转位置之后。)就我个人而言,我总是用手来表示旋转-只有很少的形状,这样编码很容易。基本上我有(作为伪代码)
至少在概念上-直接在形状中的点的多维数组也可以做到这一点:)因为每个形状只有4个可能的方向,为什么不为形状使用一个状态数组,而顺时针或逆时针旋转只是增加或减少形状状态的索引(索引为环绕)?我认为这可能比执行旋转计算之类的更快。这就是我最近在基于jQuery/CSS的俄罗斯方块游戏中所做的 计算出块的中心(用作枢轴点),即块形状的中心。 称之为(px,py) 构成块形状的每个砖都将围绕该点旋转。 对于每个砖,可以应用以下计算 如果每个砖的宽度和高度为q,砖的当前位置(左上角)为(x1,y1),新砖的位置为(x2,y2): 要反向旋转,请执行以下操作:
x2 = (px + py - y1 - q)
y2 = (x1 + py - px)
此计算基于二维仿射矩阵变换。
如果您对我是如何做到这一点感兴趣,请告诉我。如果您是在python中进行此操作的,则使用基于单元格的方法而不是坐标对,旋转嵌套列表非常简单
rotate = lambda tetrad: zip(*tetrad[::-1])
# S Tetrad
tetrad = rotate([[0,0,0,0], [0,0,0,0], [0,1,1,0], [1,1,0,0]])
我从矩阵旋转推导出一个旋转算法。总而言之:如果您有组成块的所有单元格的坐标列表,例如[(0,1),(1,1),(2,1),(3,1)]或[(1,0),(0,1),(1,1),(2,1)]: 您可以使用
x_new = y_old
y_new = 1 - (x_old - (me - 2))
用于顺时针旋转和
x_new = 1 - (y_old - (me - 2))
y_new = x_old
用于逆时针旋转
me
是块的最大范围,即i块为4
,O块为2
,所有其他块为3
。只能通过对矩阵应用数学运算来旋转矩阵。如果你有一个矩阵,说:
Mat A = [1,1,1]
[0,0,1]
[0,0,0]
若要旋转它,请将其乘以转置,然后再乘以该矩阵([I]dentity[H]orizontaly[M]irrored):
然后您将有:
Mat Rotation = Trn(A)*IHM(A) = [1,0,0]*[0,0,1] = [0,0,1]
[1,0,0] [0,1,0] = [0,0,1]
[1,1,0] [1,0,0] = [0,1,1]
注:旋转中心将是矩阵的中心,在本例中为(2,2)。对于3x3大小的俄罗斯方块 翻转你作品的x和y 然后交换外部列
有一段时间,当我试图弄清楚轮换如何适用于我的俄罗斯方块游戏时,我发现了这个问题,这是我在堆栈溢出中发现的第一个问题。尽管这个问题已经很老了,但我认为我的输入将帮助其他试图从算法上解决这个问题的人。首先,我不同意硬编码每个片段和旋转会更容易。Gamecat的回答是正确的,但我想详细说明一下。以下是我在Java中用来解决旋转问题的步骤
public synchronized void rotateLeft(){
Point[] rotatedCoordinates = new Point[MAX_COORDINATES];
for(int i = 0; i < MAX_COORDINATES; i++){
// Translates current coordinate to be relative to (0,0)
Point translationCoordinate = new Point(coordinates[i].x - origin.x, coordinates[i].y - origin.y);
// Java coordinates start at 0 and increase as a point moves down, so
// multiply by -1 to reverse
translationCoordinate.y *= -1;
// Clone coordinates, so I can use translation coordinates
// in upcoming calculation
rotatedCoordinates[i] = (Point)translationCoordinate.clone();
// May need to round results after rotation
rotatedCoordinates[i].x = (int)Math.round(translationCoordinate.x * Math.cos(Math.PI/2) - translationCoordinate.y * Math.sin(Math.PI/2));
rotatedCoordinates[i].y = (int)Math.round(translationCoordinate.x * Math.sin(Math.PI/2) + translationCoordinate.y * Math.cos(Math.PI/2));
// Multiply y-coordinate by -1 again
rotatedCoordinates[i].y *= -1;
// Translate to get new coordinates relative to
// original origin
rotatedCoordinates[i].x += origin.x;
rotatedCoordinates[i].y += origin.y;
// Erase the old coordinates by making them black
matrix.fillCell(coordinates[i].x, coordinates[i].y, Color.black);
}
// Set new coordinates to be drawn on screen
setCoordinates(rotatedCoordinates.clone());
}
public-synchronized void rotateLeft(){
点[]旋转坐标=新点[最大坐标];
对于(int i=0;iMat A = [1,1,1]
[0,0,1]
[0,0,0]
IHM(A) = [0,0,1]
[0,1,0]
[1,0,0]
Mat Rotation = Trn(A)*IHM(A) = [1,0,0]*[0,0,1] = [0,0,1]
[1,0,0] [0,1,0] = [0,0,1]
[1,1,0] [1,0,0] = [0,1,1]
public synchronized void rotateLeft(){
Point[] rotatedCoordinates = new Point[MAX_COORDINATES];
for(int i = 0; i < MAX_COORDINATES; i++){
// Translates current coordinate to be relative to (0,0)
Point translationCoordinate = new Point(coordinates[i].x - origin.x, coordinates[i].y - origin.y);
// Java coordinates start at 0 and increase as a point moves down, so
// multiply by -1 to reverse
translationCoordinate.y *= -1;
// Clone coordinates, so I can use translation coordinates
// in upcoming calculation
rotatedCoordinates[i] = (Point)translationCoordinate.clone();
// May need to round results after rotation
rotatedCoordinates[i].x = (int)Math.round(translationCoordinate.x * Math.cos(Math.PI/2) - translationCoordinate.y * Math.sin(Math.PI/2));
rotatedCoordinates[i].y = (int)Math.round(translationCoordinate.x * Math.sin(Math.PI/2) + translationCoordinate.y * Math.cos(Math.PI/2));
// Multiply y-coordinate by -1 again
rotatedCoordinates[i].y *= -1;
// Translate to get new coordinates relative to
// original origin
rotatedCoordinates[i].x += origin.x;
rotatedCoordinates[i].y += origin.y;
// Erase the old coordinates by making them black
matrix.fillCell(coordinates[i].x, coordinates[i].y, Color.black);
}
// Set new coordinates to be drawn on screen
setCoordinates(rotatedCoordinates.clone());
}
oldShapeMap[3][3] = {{1,1,0},
{0,1,0},
{0,1,1}};
bool newShapeMap[3][3] = {0};
int gridSize = 3;
for(int i=0;i<gridSize;i++)
for(int j=0;j<gridSize;j++)
newShapeMap[i][j] = oldShapeMap[j][(gridSize-1) - i];
/*newShapeMap now contain:
{{0,0,1},
{1,1,1},
{1,0,0}};
*/
require 'matrix'
shape = shape.map{|arr|(Matrix[arr] * Matrix[[0,-1],[1,0]]).to_a.flatten}
private void rotateClockwise()
{
if(rotatable > 0) //We don't rotate tetromino O. It doesn't have central square.
{
int i = y1 - y0;
y1 = (y0 + x1) - x0;
x1 = x0 - i;
i = y2 - y0;
y2 = (y0 + x2) - x0;
x2 = x0 - i;
i = y3 - y0;
y3 = (y0 + x3) - x0;
x3 = x0 - i;
}
}
private void rotateCounterClockwise()
{
if(rotatable > 0)
{
int i = y1 - y0;
y1 = (y0 - x1) + x0;
x1 = x0 + i;
i = y2 - y0;
y2 = (y0 - x2) + x0;
x2 = x0 + i;
i = y3 - y0;
y3 = (y0 - x3) + x0;
x3 = x0 + i;
}
}
originalMatrix =
[0, 0, 1]
[1, 1, 1]
clockwise90DegreesRotatedMatrix = reverseTheOrderOfColumns(Transpose(originalMatrix))
anticlockwise90DegreesRotatedMatrix = reverseTheOrderOfRows(Transpose(originalMatrix))
originalMatrix =
x y z
a[0, 0, 1]
b[1, 1, 1]
transposed = transpose(originalMatrix)
a b
x[0, 1]
y[0, 1]
z[1, 1]
counterClockwise90DegreesRotated = reverseTheOrderOfRows(transposed)
a b
z[1, 1]
y[0, 1]
x[0, 1]
clockwise90DegreesRotated = reverseTheOrderOfColumns(transposed)
b a
x[1, 0]
y[1, 0]
z[1, 1]
pieces = [
[(0,0),(0,1),(0,2),(0,3)],
[(0,0),(0,1),(1,0),(1,1)],
[(1,0),(0,1),(1,1),(1,2)],
[(0,0),(0,1),(1,0),(2,0)],
[(0,0),(0,1),(1,1),(2,1)],
[(0,1),(1,0),(1,1),(2,0)]
]
def get_piece_dimensions(piece):
max_r = max_c = 0
for point in piece:
max_r = max(max_r, point[0])
max_c = max(max_c, point[1])
return max_r, max_c
def rotate_piece(piece):
max_r, max_c = get_piece_dimensions(piece)
new_piece = []
for r in range(max_r+1):
for c in range(max_c+1):
if (r,c) in piece:
new_piece.append((c, max_r-r))
return new_piece
private static char[][] rotateMatrix(char[][] m) {
final int h = m.length;
final int w = m[0].length;
final char[][] t = new char[h][w];
for(int y = 0; y < h; y++) {
for(int x = 0; x < w; x++) {
t[w - x - 1][y] = m[y][x];
}
}
return t;
}