用填充的填充顺序生成填充的数独板而不是

时间:2018-01-16 15:04:04

标签: c# algorithm shuffle sudoku

所以我试图弄清楚为什么按照我生成字段的顺序填充数独板的速度比填充顺序要快几倍,并且我无法得出任何合理的结论。

填充和检查的速度应该大致相同,无论字段是否被洗牌,只有明显的区别是填充框以洗牌顺序导致主循环容易进行60.000.000+迭代不确定平均多少,因为我没耐心检查。按照它们的生成顺序填充它们通常会在< 1.000次迭代很少超过它,基本上从未超过5.000。

我确实理解代码并不严格遵循C#标准,但它是我应该制作的项目而且它不是我的主要语言,可能有一些可能的优化,但它&#39 ; s不是我感兴趣的所有我想知道为什么改变填充框的顺序导致过程花费更长的时间。

编辑:忘记附加创建/填充框填写/创建框顺序的顺序:

img

Edit2:更简洁的改述问题:

问题是为什么从图像开始按顺序生成一个有效的完全填充的数独板会产生更少的无效板,从而需要回溯,与以选择字段的随机顺序生成板相比?

example of random order

以下是用于项目https://github.com/Piterm21/sudoku

的代码

以下是代中使用的所有部件。

filledBox类:

public class filledBox
{
    public int textBoxIndex;
    public int value;
    public int nextIndexToTry;
    public int[] values;
    public int lineIndex;
    public int columnIndex;
    public int groupIndex;
}

这是一个主循环:

filledBox[] boxes = this.shuffleBoxesCreateCheckingLists();

long iter = 0;
int nextIndexToFill = 0;
while (nextIndexToFill != 81) {
    for (; boxes[nextIndexToFill].nextIndexToTry < 9; boxes[nextIndexToFill].nextIndexToTry++) {
        // check if is valid
        if (!createsError(boxes[nextIndexToFill])) {
            boxes[nextIndexToFill].value = boxes[nextIndexToFill].values[boxes[nextIndexToFill].nextIndexToTry];
            nextIndexToFill++;
            break;
        }

        if (boxes[nextIndexToFill].nextIndexToTry == 8) {
            boxes[nextIndexToFill].nextIndexToTry = 0;
            boxes[nextIndexToFill].value = 0;
            nextIndexToFill--;
            boxes[nextIndexToFill].nextIndexToTry++;

            while (boxes[nextIndexToFill].nextIndexToTry == 9) {
                boxes[nextIndexToFill].nextIndexToTry = 0;
                boxes[nextIndexToFill].value = 0;
                nextIndexToFill--;
                boxes[nextIndexToFill].nextIndexToTry++;
            }

            break;
        }
    }

    iter++;
}

System.Diagnostics.Debug.WriteLine(iter);

生成包含用于检查错误的列表的框:

List<filledBox>[] generationLines;
List<filledBox>[] generationColumns;
List<filledBox>[] generationGroups;

public filledBox[] shuffleBoxesCreateCheckingLists()
{
    filledBox[] boxes = new filledBox[81];

    for (int i = 0; i < 81; i++) {
        boxes[i] = new filledBox();
        boxes[i].values = new int[9]{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        boxes[i].values = shuffle(boxes[i].values, true);
    }

    generationLines = new List<filledBox>[9];
    generationColumns = new List<filledBox>[9];
    generationGroups = new List<filledBox>[9];

    for (int i = 0; i < 9; i++) {
        generationLines[i] = new List<filledBox>();
        generationColumns[i] = new List<filledBox>();
        generationGroups[i] = new List<filledBox>();
    }

    int boxIndex = 0;
    for (int y = 0; y < 3; y++) {
        for (int x = 0; x < 3; x++) {
            for (int innerY = 0; innerY < 3; innerY++) {
                for (int innerX = 0; innerX < 3; innerX++) {
                    int subPanelIndex = x + y * 3;
                    int lineIndex = innerY + y * 3;
                    int columnIndex = innerX + x * 3;

                    boxes[boxIndex].textBoxIndex = boxIndex;
                    boxes[boxIndex].groupIndex = subPanelIndex;
                    boxes[boxIndex].columnIndex = columnIndex;
                    boxes[boxIndex].lineIndex = lineIndex;
                    boxes[boxIndex].nextIndexToTry = 0;
                    boxes[boxIndex].value = 0;

                    generationLines[lineIndex].Add(boxes[boxIndex]);
                    generationColumns[columnIndex].Add(boxes[boxIndex]);
                    generationGroups[subPanelIndex].Add(boxes[boxIndex]);
                    boxIndex++;
                }
            }
        }
    }

#if !fast
    boxes = shuffle(boxes);
#endif

    return boxes;
}

改组代码:

public T[] shuffle<T> (T[] array)
{
    int i = array.Length;

    while (i > 1) {
        i--;

        int j = rnd.Next(0, i - 1);
        T temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    return array;
}

负责检查错误的代码:

    public bool hasError (List<filledBox> list, filledBox box)
    {
        bool result = false;

        foreach (filledBox filledBoxToCheck in list) {
            if (filledBoxToCheck.value == box.values[box.nextIndexToTry]) {
                if (box.lineIndex != filledBoxToCheck.lineIndex ||
                    box.columnIndex != filledBoxToCheck.columnIndex) {
                    result = true;
                    break;
                }
            }
        }

        return result;
    }

    public bool createsError (filledBox box)
    {
        bool result = false;

        if (hasError(generationGroups[box.groupIndex], box)) {
            result = true;
        } else if (hasError(generationLines[box.lineIndex], box)) {
            result = true;
        } else if (hasError(generationColumns[box.columnIndex], box)) {
            result = true;
        }

        return result;
    }

0 个答案:

没有答案