algorithm - 俄罗斯方 block 旋转算法

标签 algorithm rotation tetris

表示和旋转俄罗斯方 block 游戏的最佳算法(和解释)是什么?我总是觉得棋子旋转和表示方案令人困惑。

大多数俄罗斯方 block 游戏似乎在每次旋转时都使用天真的“重新制作方 block 阵列”:

http://www.codeplex.com/Project/ProjectDirectory.aspx?ProjectSearchText=tetris

但是,有些使用预构建的编码数字和位移位来表示每个片段:

http://www.codeplex.com/wintris

有没有一种方法可以使用数学来做到这一点(不确定这是否适用于基于单元的电路板)?

最佳答案

当我试图弄清楚旋转如何适用于我的俄罗斯方 block 游戏时,这是我在堆栈溢出中发现的第一个问题。尽管这个问题很老,但我认为我的输入将帮助其他人尝试通过算法解决这个问题。首先,我不同意对每个部分进行硬编码和旋转会更容易。 Gamecat 的回答是正确的,但我想详细说明一下。以下是我在 Java 中解决旋转问题的步骤。

  1. 对于每个形状,确定其原点。我使用了图表上的点 this page分配我的原点。请记住,根据您的实现,您可能必须在每次用户移动棋子时修改原点。

  2. 旋转假定原点位于点 (0,0),因此您必须先平移每个 block 才能旋转。例如,假设您的原点当前位于 (4, 5) 点。这意味着在旋转形状之前,每个 block 必须在 x 坐标中平移 -4,在 y 坐标中平移 -5 以相对于 (0,0)。

  3. 在 Java 中,典型的坐标平面从最左上角的点 (0,0) 开始,然后向右和向下增加。为了在我的实现中对此进行补偿,我在旋转之前将每个点乘以 -1。

  4. 这是我用来计算逆时针旋转后新的 x 和 y 坐标的公式。有关这方面的更多信息,我会在 Rotation Matrix 上查看维基百科页面。 . x' 和 y' 是新坐标:

    x' = x * cos(PI/2) - y * sin(PI/2) 和 y' = x * sin(PI/2) + y * cos(PI/2) .

  5. 对于最后一步,我只是以相反的顺序执行了步骤 2 和 3。所以我再次将我的结果乘以 -1,然后将 block 转换回它们的原始坐标。

这是对我有用的代码(在 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());
}

这个方法是将你的形状向左旋转所需的全部方法,结果证明这比为每个形状定义每个旋转要小得多(取决于你的语言)。

关于algorithm - 俄罗斯方 block 旋转算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/233850/

相关文章:

c++ - 为什么此C++程序不打印任何内容?

objective-c - UIView 在所有不随屏幕旋转的东西前面?

python - 将子列表放置到其他子列表中

python - 我怎样才能找到一个大字符串的最合适的子序列?

arrays - 从数组中选择其和为最小可能正数的元素组合

c - 将图像转为灰度图

javascript - 在 JavaScript 俄罗斯方 block 中绘制新的俄罗斯方 block

c++ - 使用opencv GPU旋转图像

如果微调器打开(列出)并且您旋转设备,则对话框上的 Android 微调器会崩溃

python - 我的 pygame 俄罗斯方 block 游戏总是卡住