随机生成唯一的数字网格

时间:2011-05-17 13:39:30

标签: c# random

我有一个2D整数数组,5x5,我已经制作了一个解决方案,在每个数组单元中随机生成数字1 - 5:

public int[,] generateGrid()
{
    int seed = DateTime.Now.Second; // generate seed
    Random rand = new Random(seed); // initialise random number with seed

    int[,] grid = new int[_gridSize, _gridSize]; // create 2D array for grid

    for (int i = 0; i < _gridSize; i++) // loop through rows
    {
        for (int j = 0; j < _gridSize; j++) // loop throug columns
        {
            int value = 0; // initialise the value to be entered into cell

            while (value == 0) // while value is invalid ( "0" ) keep generating new number
            {
                value = rand.Next() % _gridSize + 1; // generate value from 0 - gridsize
                grid[i, j] = value; // input value. Note: if value = 0, the loop will regenerate a new value
            }

        }
    }
    return grid; 
}

现在这段代码完成了它的工作。 (不确定效率 - 任何关于效率的额外建议都会有所帮助。)

但我的问题是,每列和每行只能包含数字一次! (而不是像Sudoku。)我不知道如何做到这一点(或者最好的方法)。

我的第一个想法是创建一个堆栈,并推送堆栈中每行创建的所有值,然后检查它以查看该行是否已包含该值。如果是,则生成新值,再次检查等。 但是迭代堆栈也是一个坏主意,这对于检查行是有好处的,但是当检查列的唯一性时,它会有点困难!

基本上,我如何使所有行和列都是唯一的,但每次仍然能够随机生成。什么是最好的方法呢?

3 个答案:

答案 0 :(得分:1)

我找到了一个解决方案,我愿意发布任何其他人在这篇文章中寻找答案的绊脚石。要生成一个唯一的数字网格N x N(虽然我只测试了5x5), 以下代码应该可以解决问题:

// C#中的内容是什么

public int[,] generateGrid() // POSSIBLE UPDATE:: WHEN RESETING GRID ROW, REMEMBER PREVIOUS ORDER TO AVOID SAME COMFLICTION TWICE
{
    Random rand = new Random();
    ArrayList availableColumnNumbers = new ArrayList();
    ArrayList availableRowNumbers = new ArrayList();
    ArrayList availableNumbers = new ArrayList();
    int[,] grid = new int[_gridSize, _gridSize];

    availableColumnNumbers = resetArrayList(); // create a list that holds the numbers 1 - Grid Size
    availableRowNumbers = resetArrayList(); // create a list that holds the numbers 1 - Grid Size

    for (int row = 0; row < _gridSize; row++) // loop through rows
    {
        for (int column = 0; column < _gridSize; column++) // loop through columns
        {
            if (row == 0) // if row to be filled if the first row
            {
                int position = rand.Next(availableRowNumbers.Count); // Generate a random position
                grid[row, column] = (int)availableRowNumbers[position]; // place available row numbers
                availableRowNumbers.RemoveAt(position); // update available row numbers
            }
            else // row to be filled has constraints. Fill in, taking constraints into consideration
            {
                // update available column number, finds out what values are already in the column, and generates the only available values 
                availableColumnNumbers = getAvailableColumnNumbers(grid, column);
                // combine available Rows and Columns to get a list of available numbers for that cell
                availableNumbers = getSimilarNumbers(availableRowNumbers, availableColumnNumbers);

                if (availableNumbers.Count != 0) // if there are available numbers to place,
                {
                    int position = rand.Next(availableNumbers.Count);
                    grid[row, column] = (int)availableNumbers[position]; // place available number
                    availableRowNumbers.Remove((int)availableNumbers[position]); // update available row numbers
                }
                else // Confliction: There are no available numbers (restart entire row)
                {
                    grid = resetRow(grid, row); // reset the entire row where confliction occured
                    column = -1; // start again at begining of column
                    availableRowNumbers = resetArrayList(); // reset Array List
                }
            }
        }
        availableRowNumbers = resetArrayList();// reset available row array
    }
    return grid;

这个解决方案提供了一些功能,使得源不会被发布......但是对于任何狂热的开发人员来说,它们都非常直接:...

快乐的编码!

亚历

答案 1 :(得分:0)

我想你可能不得不这样做有点像解决数独。换句话说,最初每个单元格可以包含5个值中的任何一个:因此您可以随机设置第一个单元格,没有任何限制。然后设置下一个单元格:现在有一个限制,它不能有第一个单元格的值(它在同一行),所以你可能需要花几个去获得一个有效的数字。

只需继续处理每一行和每一行,始终检查已经在此行上设置的值的左侧(下列索引),并检查(下行索引)已在此列上设置的值。如果您尝试将单元格设置为此行或列上已使用的值,请再试一次。

如果您需要使用不同大小的网格,这应该是可扩展的。如果有必要,我会留给你如何优化它(提示:设置最后一个单元格最终可能比任何其他单元格更长,即使它只有一个可能的值)。

答案 2 :(得分:0)

我认为你不需要关心这么小的网格(甚至不是更大的网格)的效率。

最简单的解决方案是通过简单地迭代网格来检查当前行和列中您要写入该单元格的值。