【问题标题】:How to Rotate a 2D Array of Integers如何旋转二维整数数组
【发布时间】:2009-03-14 18:45:45
【问题描述】:

我正在编写俄罗斯方块克隆,在我的游戏中,我将我的 tetromino 块存储为 4x4 块数组。我现在需要能够旋转数组中的整数位置,以便得到一个旋转的俄罗斯方块块。我不能简单地旋转纹理,因为我所有的碰撞检测等都被设计为与 2D 数组一起使用。该游戏是使用 XNA 用 C# 编写的。

我怎么可能将我的二维整数数组顺时针/逆时针旋转 90 度。

以下是我的“L”块的存储方式作为示例。

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

感谢您的帮助。

【问题讨论】:

    标签: c# c++ arrays math


    【解决方案1】:

    如果是二维数组,可以通过复制不同的数组访问顺序来实现旋转。

    即,对于顺时针旋转,请尝试:

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

    逆时针类似。

    【讨论】:

    • 很好的解决方案,但考虑到问题域,过大了。
    • 我正在投票,它应该被标记为解决方案。不确定你的意思 rde6173,除非你也保证存储 4 个方向数组。
    • 这就是他的建议。这样做有好处,但这直接回答了这个问题——我并不是要建议替代设计。
    • 没问题 :) 很高兴我能帮上忙。
    • 这并不过分,因为它可以节省制作那些预先转换的数组的手工劳动,并且如果在基本俄罗斯方块之外的游戏中投入更多的工作,它可以扩展到非四联体。 (明天我的投票重置时会 +1 :)
    【解决方案2】:

    不要使用代码旋转片段。只需存储一组不同的工件方向,并在工件旋转时循环遍历它们。无需在俄罗斯方块游戏中动态旋转它们。

    由于问题域是俄罗斯方块,您会发现旋转算法会导致不良影响,例如细长的 Tetronimo 不会在两个位置之间交替(就像在现实中那样)。

    【讨论】:

    • -1;存储每块的 4 个方向而不仅仅是旋转没有任何优势。你应该专注于回答他的问题,而不是劝阻他,除非他犯了严重的错误;他当然不是。
    • 按照上面的建议,编写一个双 for 循环将花费我更少的时间。
    • 佝偻病,轻轻松松。我已经更新了我的答案,以说明为什么在这种情况下轮换是一个坏主意。
    • 这与您作为开发人员编写所需的时间无关,而与执行所需的时间有关。请记住,编译器可能擅长优化循环,但在常量方面它们甚至更好。
    • 我同意乔恩的观点,我自己也一直在考虑这个问题。如果您旋转阵列,则块的旋转方式与原始游戏中的旋转方式不同。它们似乎围绕中心旋转。
    【解决方案3】:

    在经典俄罗斯方块中,对象的排列非常少。我会在 4 个位置的每一个位置为每个“tetromino”设置一个常量数组,并使用简单的逻辑根据输入选择合适的位置。

    为什么要浪费 CPU 周期来尝试旋转它?

    【讨论】:

    • 在这种情况下,数学非常简单,旋转它可能和基于当前块样式 + 位置进行排列搜索一样快。
    • 我还要补充一点,从游戏玩法和设计的角度来看,预先设置旋转可能会更好。当你拿到长的 4x1 件时你会怎么做?如果你旋转它两次,它真的应该是一个完整的空间(如果你使用纯数学的话)?
    • CPU 周期在这种情况下不是问题。不要试图通过考虑“浪费 CPU 周期”来过度优化。无论您是存储 4 种不同的排列并选择一个,还是循环并旋转数组,任何一种方式的时间跨度都非常小,根本不重要。投反对票。
    • 我有一个 2.4GHz Core 2 Duo 处理器,更不用说检查整数的双 for 循环正在执行 8 字节乘以 16 的比较。这对 CPU 来说几乎没有任何意义。另外,如果我有一天想要一个 5x5 矩阵怎么办?我必须重新编码。
    【解决方案4】:

    如果要旋转 4 x 4 块,只需移动位置:

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

    每个 A 移动到下一个 A,对于 B、C 和 D 也是如此。

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

    【讨论】:

    • 我认为你的图片有点不对劲,不确定你想用它澄清什么,箭头似乎指向 b -> c 和 a -> c 而不是支持你的指示。 fmsf,长大了。
    【解决方案5】:

    我会存储“细胞”的 (x, y) 坐标并使用旋转矩阵来旋转它们。 例如,请参阅Drawing a Rotated Rectangle。您可能必须将结果四舍五入到最接近的 0.5 增量。

    【讨论】:

      【解决方案6】:

      顺时针和逆时针的js代码:

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

      【讨论】:

        【解决方案7】:
        int[,] source = { { 1,2,3 }, {4,5,6 }, { 7,8,9} };
        int[,] result = new int[3,3];
        var rows = source.GetLength(0);
        var cols = source.GetLength(1);
        
        for (var r=0; r<rows; r++)
        {
            for (var c = 0; c < cols; c++)
            {
                result[r, c] = source[rows - 1 - c, r];
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-08-08
          • 2021-11-02
          • 2022-01-07
          • 2011-06-01
          • 1970-01-01
          相关资源
          最近更新 更多