Search Unity

Resolved How to get the index of a rotated 2d array

Discussion in 'Scripting' started by VadanaPon, Nov 24, 2022.

  1. VadanaPon

    VadanaPon

    Joined:
    Jul 5, 2022
    Posts:
    45
    Hi, I have a 2d array that can be rotated counterclockwise, I already have that, but what I need is something like this:

    Untitled.png

    And this is what i have:
    Code (CSharp):
    1.     public int[,] originalCells = new int[2, 3] { { 0, 0, 2 }, { 1, 1, 1 } };
    2.     public int[,] currentCells;
    3.  
    4.     [HideInInspector] public int rotation = 0; // To know on what rotation the item is
    5.  
    6.     void Start()
    7.     {
    8.         currentCells= originalCells;
    9.     }
    10.  
    11.     public void RotateCounterclockwise()
    12.     {
    13.         // The rotated size is the original size inverted
    14.         int[,] rotatedCells = new int[currentCells.GetLength(1), currentCells.GetLength(0)];
    15.  
    16.         int rowCounter;
    17.         int columnCounter = 0;
    18.  
    19.         for (int x = 0; x < currentCells.GetLength(0); x++)
    20.         {
    21.             rowCounter = 0;
    22.  
    23.             // The last column of the first row should be 0, 0
    24.             for (int y = currentCells.GetLength(1) - 1; y >= 0; y--)
    25.             {
    26.                 rotatedCells[rowCounter, columnCounter] = currentCells[x, y];
    27.  
    28.                 rowCounter++;
    29.             }
    30.  
    31.             columnCounter++;
    32.         }
    33.  
    34.         currentCells= rotatedCells;
    35.  
    36.         rotation++; // Register the rotation
    37.  
    38.         if (rotation > 3)
    39.         {
    40.             rotation = 0;
    41.         }
    42.     }
    43.  
    44.     public bool CellHasValue(int row, int column, int valueToCompareTo)
    45.     {
    46.         Vector2Int index = GetReferencedCell(row, column);
    47.  
    48.         if (currentCells[index.x, index.y] == valueToCompareTo)
    49.         {
    50.             return true;
    51.         }
    52.         else
    53.         {
    54.             return false;
    55.         }
    56.     }
    57.  
    58.     public Vector2Int GetReferencedCell(int row, int column) // Point to a specific index even when the item is rotated
    59.     {
    60.         // The code goes here
    61.  
    62.         return Vector2Int.zero;
    63.     }
    I could create a class and give each an ID and then loop through all of them but there has to be a more elegant way

    I appreciate any help
     
    Last edited: Nov 24, 2022
  2. mopthrow

    mopthrow

    Joined:
    May 8, 2020
    Posts:
    348
    Hmm maybe I didn't understand your problem, but couldn't you use the same algorithm that you used to rotate the array to rotate any coordinates you request?

    Sorry if I mussunderstand.
     
  3. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,105
    Take for example such a matrix
    Code (csharp):
    1.        0 1 2 3 4  < columns
    2. rows 0 K . . . .
    3.   v  1 . . . A .
    4.      2 . . . . .
    5.      3 . . X . .
    6.      4 . . . . .
    If we specify letters K, A, X, in (row, column) standard they would look like this
    K = (0, 0)
    A = (1, 3)
    X = (3, 2)

    If you rotate that counter-clockwise
    you get the following matrix
    Code (csharp):
    1.        0 1 2 3 4  < columns
    2. rows 0 . . . . .
    3.   v  1 . A . . .
    4.      2 . . . X .
    5.      3 . . . . .
    6.      4 K . . . .
    K = (4, 0)
    A = (1, 1)
    X = (2, 3)

    Let's do the rest of them
    Code (csharp):
    1.        0 1 2 3 4  < columns
    2. rows 0 . . . . .
    3.   v  1 . . X . .
    4.      2 . . . . .
    5.      3 . A . . .
    6.      4 . . . . K
    K = (4, 4)
    A = (3, 1)
    X = (1, 2)

    Code (csharp):
    1.        0 1 2 3 4  < columns
    2. rows 0 . . . . K
    3.   v  1 . . . . .
    4.      2 . X . . .
    5.      3 . . . A .
    6.      4 . . . . .
    K = (0, 4)
    A = (3, 3)
    X = (2, 1)

    There's got to be some rule governing this right?
    Well, for starters the axes look flipped between each image. And also one of the axes gets mirrored.
    For example, if you take a look at A
    It starts at (1, 3), moves to (1, 1), then (3, 1), and finally ends up at (3, 3)
    Well 3 is a mirror value of 1, because there are 5 elements in total (-1 because it starts from 0)
    5 - 1 - 1 = 3

    With X you see something similar going on, but the loop breaks
    (3, 2) => (2, 3) => (1, 2) => (2, 1)

    Let's try to make a transformation that would do this one step at a time
    That would be
    (next_row, next_column) = (mirrored(current_column), current_row)

    Let's now formalize this solution with Vector2Int
    Code (csharp):
    1. int mirrorValue(int value, int max) => max - value - 1;
    2.  
    3. Vector2Int rotateCCW(Vector2Int pos, int size) {
    4.   return new Vector2Int(
    5.     mirrorValue(pos.y, size),
    6.     pos.x
    7.   );
    8. }
    And likewise
    Code (csharp):
    1. Vector2Int rotateCW(Vector2Int pos, int size) {
    2.   return new Vector2Int(
    3.     pos.y,
    4.     mirrorValue(pos.x, size)
    5.   );
    6. }
    Another, perhaps more logical way of writing this is to simply negate instead of mirroring, which coincides with the mathematical notion of computing a 2D orthonormal in linear algebra. Then if you end up with a negative value, you simply wrap that index around (in other words, you add width or height to it).

    Code (csharp):
    1. Vector2Int rotateCCW(Vector2Int pos, int size) {
    2.   return new Vector2Int(
    3.     -pos.y + (size - 1), // which is the same thing as before
    4.     pos.x
    5.   );
    6. }

    Test
    Code (csharp):
    1. var myPos = new Vector2Int(3, 2);
    2. myPos = rotateCCW(myPos, 5); // 2, 3
    3. myPos = rotateCCW(myPos, 5); // 1, 2
    4. myPos = rotateCCW(myPos, 5); // 2, 1
    5. myPos = rotateCCW(myPos, 5); // 3, 2
    I will leave (column, row) notation as an exercise.
    Also if your width and height differ you'd have to alternate between them.
     
    Last edited: Nov 24, 2022
    Bunny83 likes this.
  4. VadanaPon

    VadanaPon

    Joined:
    Jul 5, 2022
    Posts:
    45
    Hi, thanks for the in-depth answer! I'm gonna try that as soon as i can