如何从一维 int 数组返回数字网格?

How to return a grid of numbers from 1-D int array?

提问人:nleslie 提问时间:9/8/2019 最后编辑:Roxana Shnleslie 更新时间:9/10/2019 访问量:739

问:

目前,我有一个 1D 整数数组,用于形成一个 9x9 的数字网格(但可以是任何大小)。 我想输入一个索引并返回一个 3x3 的数字网格,有效地将 9x9 网格分解为 3x3 网格(想想数独)。

到目前为止,我已经尝试了两个嵌套循环,一个循环网格的高度,另一个循环网格的宽度。但是我无法让它与第一个 3x3 网格以外的任何东西一起使用,或者当大小从 9x9 发生变化时。

到目前为止,我所拥有的:

int squareWidth = 3;
int squareHeight = 3;

int index = 0;
for (int i = 0; i < 3; i++)
{
    for (int j = index; j < 3; j++)
    {
     Console.WriteLine(array[j]);
    }
   index+=9;
}

4x4 网格示例应返回 2x2 网格,但在一维数组中。

假设第一个 2x2 网格是 1,2,2,4。在索引 0、1、4、5 处找到的数字。

第二个 2x2 网格是 7,2,4,5。在索引 2、3、6、7 处找到的数字。

var gameboard = new int[] { 
1, 2, 7, 2,
2, 4, 4, 5,
4, 2, 1, 3,
3, 1, 2, 2 };

GetByGrid(2);

应该回来

7,2,4,5

由于我将 2 输入到它应该返回 2x2 网格GetByGrid()

GetByGrid(3);

应该回来

4,2,3,1

进一步阐明了网格是如何分解的。这是一个带有四个 2x2 网格的 4x4 游戏板。一个 9x9 的游戏板将有 9 个 3x3 网格。

1,2 | 7,2
2,4 | 4,5
---------
4,2 | 1,3
3,1 | 2,2
C# 数组 DataGrid 与语言无关

评论

0赞 Chetan 9/8/2019
你能解释一下如何得到这些答案的逻辑吗?
0赞 TheGeneral 9/8/2019
到底是怎么回事,回来GetByGrid(3)4,2,3,1
0赞 9/8/2019
所有数组都是严格的正方形吗?您可以从 4x4 网格获得 4 个网格,从 9x9 网格获得 9 个网格,但是如何处理 5x5 网格?分解网格的标准是什么?GetByGrid(2) 也可以在您的示例中返回,如果我决定将您的初始网格分解为 8 个子网格,而不是 4 个子网格。是否要传递另一个参数来指定应如何分解网格?7,2
0赞 nleslie 9/8/2019
网格大小是在另一个函数中手动设置的。但是我们可以预期所有网格都是正方形的,并且均匀地分解成相同大小的网格。完整的 1D 阵列将始终有足够的数字来形成 4x4 板、9x9 板、16x16 等。
1赞 mike gold 9/8/2019
如果您知道网格的尺寸,并且知道所需的子维空间的每个元素的(行、列)坐标,您应该能够使用公式(维度)* 行 + 列来计算出一维数组中要从中提取值的位置。例如上面,4,2,3,1 位于(第 2 行,第 0 列)、(第 2 行,第 1 列)、(第 3 行,第 0 列)、(第 3 行,第 1 列)。将其从 1d 数组中取出的公式是 4*行 + 列。对于第 3 行列,第 1 列,这是 4*3 + 1 = 13(请记住,行和列从 0 开始)

答:

0赞 nleslie 9/8/2019 #1

感谢您的帮助

这是我如何解决的

高度、宽度、行的长度都在其他地方定义

public void GridToSquare(squareIndex)
{
int rowNum = squareIndex / (maxNum / width) * height;
int colNum = squareIndex % (maxNum / width) * width;

       for (int row = rowNum; row < height + rowNum; row++)
       {
           for (int column = colNum; column < width + colNum; column++)
           {
               Console.WriteLine(theArray[maxNum * row + column]);
           }
       } 
}
1赞 John Alexiou 9/9/2019 #2

为什么不使用 OOP 并创建一个游戏板类,其中包含网格元素的索引器和返回子矩阵的方法。像这样的东西:

class Program
{
    static void Main(string[] args)
    {

        var game = new GameBoard(3);
        // Fill the board with sequencial number (the index).
        var index = 0;
        for (int i = 0; i < game.SubGridCount; i++)
        {
            for (int j = 0; j < game.SubGridCount; j++)
            {
                game[i, j] = index++;
            }
        }
        // game = 
        // +----------+----------+----------+
        // |  0  1  2 |  3  4  5 |  6  7  8 |
        // |  9 10 11 | 12 13 14 | 15 16 17 |
        // | 18 19 20 | 21 22 23 | 24 25 26 |
        // +----------+----------+----------+
        // | 27 28 29 | 30 31 32 | 33 34 35 |
        // | 36 37 38 | 39 40 41 | 42 43 44 |
        // | 45 46 47 | 48 49 50 | 51 52 53 |
        // +----------+----------+----------+
        // | 54 55 56 | 57 58 59 | 60 61 62 |
        // | 63 64 65 | 66 67 68 | 69 70 71 |
        // | 72 73 74 | 75 76 77 | 78 79 80 |
        // +----------+----------+----------+
        var data = game.ToArray();
        // [0,1,2,3,4,5...79,80]

        var A11 = game.GetSubArray(0, 0);
        // [0,1,2,9,10,11,18,19,20]
        var A12 = game.GetSubArray(0, 1);
        // [3,4,5,12,13,14,21,22,23]
        var A13 = game.GetSubArray(0, 2);
        // [6,7,8,15,16,17,24,25,25]
        var A32 = game.GetSubArray(2, 1);
        // [57,58,59,66,67,68,75,76,77]

        // In the A23 subgrid, get the (3,1) element
        var x2331 = game[1, 2, 2, 0];
        // 51
    }
}

定义为GameBoard

public class GameBoard 
{
    public GameBoard(int subGridSize)
    {
        this.SubGridSize = subGridSize;
        this.SubGridCount = subGridSize*subGridSize;
        this.Elements = new int[subGridSize*subGridSize*subGridSize*subGridSize];
    }
    public int SubGridSize { get; }
    public int SubGridCount { get; }
    int[] Elements { get; }

    public int this[int row, int col]
    {
        get => Elements[SubGridCount*row+col];
        set => Elements[SubGridCount*row+col] = value;
    }
    public int this[int grid_row, int grid_col, int row, int col]
    {
        get => Elements[SubGridCount*(grid_row*SubGridSize+row) + grid_col*SubGridSize + col];
        set => Elements[SubGridCount*(grid_row*SubGridSize+row) + grid_col*SubGridSize + col] = value;
    }

    // Make a copy of the elements
    public int[] ToArray() => Elements.Clone() as int[];

    public int[] GetSubArray(int grid_row, int grid_col)
    {
        var array = new int[SubGridCount];
        for (int i = 0; i < SubGridSize; i++)
        {
            var first_element = SubGridCount * (grid_row*SubGridSize+i) + grid_col* SubGridSize;
            for (int j = 0; j < SubGridSize; j++)
            {
                array[i*SubGridSize + j] = Elements[first_element +j];
            }
        }
        return array;
    }
}

未来工作

为了获得更大的灵活性,可以添加一个包含元素的类,以便可以使用更多特定于子网格的方法。例如:SubGridn×n

        var S32 = game.GetSubGrid(2, 1);
        Debug.WriteLine(S32.ToString());
        // 57  58  59
        // 66  67  68
        // 75  76  77

使用定义

public class SubGrid 
{
    public SubGrid(int size)
    {
        this.Size = size;
        this.Elements = new int[size*size];
    }
    public SubGrid(int size, int[] elements)
    {
        this.Size = size;
        this.Elements  = elements;
    }
    public int Size { get; }
    public int[] Elements { get; }
    public int this[int row, int col]
    {
        get => Elements[Size*row+col];
        set => Elements[Size*row+col] = value;
    }
    public int[] ToArray() => Elements.Clone() as int[];

    public override string ToString()
    {
        const int col_size = 3;
        // print the grid
        var sb = new StringBuilder();
        for (int i = 0; i < Size; i++)
        {
            var row = Elements.Skip(i*Size).Take(Size);
            sb.AppendLine(string.Join(" ", row.Select((x) => $"{x,-col_size}")));
        }
        return sb.ToString();
    }
}