c# - 从数独解决方案中删除单元格使其成为一个谜题

标签 c# .net algorithm sudoku

我正在编写一个数独应用程序,目前正在研究游戏生成算法。我设法弄清楚如何快速生成解决方案(不是解决)。不过,我对如何删除一些数字以实际使其成为一个谜题感到困惑。我的第一个倾向是根据难度随机删除一定数量的单元格,但这不是正确的算法,因为它经常呈现无法解决或有多个解决方案的谜题。它还可能生成未反射(reflect)所请求难度的谜题。

这是我目前的代码。我删除了大部分不相关的代码,但如果您想查看未实现但在下面使用的内容,请告诉我。如果您愿意,我也可以提供我对 Puzzlefy 方法的尝试,但我选择不立即发布它,因为它明显错误(即使它“有效”)。

using System;
using System.Collections.Generic;
using System.Linq;

namespace Sudoku
{
    public class Game
    {
        public enum Difficulty
        {
            VeryEasy,
            Easy,
            Medium,
            Difficult,
            Evil
        }

        private readonly int?[,] _currentItems = new int?[9,9];
        private readonly int?[,] _solution = new int?[9,9];
        private readonly int?[,] _startingItems = new int?[9,9];
        private readonly Difficulty _difficulty;

        public Game(Difficulty difficulty)
        {
            _difficulty = difficulty;
            GenerateSolution();
            Puzzlefy();
        }

        private void GenerateSolution()
        {
            var random = new Random();
            var availableNumbers = new Stack<List<int?>>(81);
            var x = 0;
            var y = 0;

            availableNumbers.Push(AllowableNumbers(_solution, 0, 0).ToList());
            while (x < 9 && y < 9)
            {
                var currentAvailableNumbers = AllowableNumbers(_solution, x, y).ToList();
                availableNumbers.Push(currentAvailableNumbers);

                // back trace if the board is in an invalid state
                while (currentAvailableNumbers.Count == 0)
                {
                    _solution[x, y] = null;
                    availableNumbers.Pop();
                    currentAvailableNumbers = availableNumbers.Peek();
                    x -= y >= 1 ? 0 : 1;
                    y = y >= 1 ? y - 1 : 8;
                }

                var index = random.Next(currentAvailableNumbers.Count);
                _solution[x, y] = currentAvailableNumbers[index];
                currentAvailableNumbers.RemoveAt(index);

                x += y < 8 ? 0 : 1;
                y = y < 8 ? y + 1 : 0;
            }
        }

        private void Puzzlefy()
        {
            CopyCells(_solution, _startingItems);

            // remove some stuff from _startingItems

            CopyCells(_startingItems, _currentItems);
        }
    }
}

我不是在寻找代码,而是在寻找算法。我将如何从解决方案中删除数字以使其成为一个谜题?

最佳答案

这是一个paper on sudoku generation

我认为您将需要一个数独求解器,它还会计算可用解决方案的数量,然后以始终只有一个可用解决方案的方式减去数字。

可以用同样的方法给网格加数,然后检查可能解的个数,当解数大于1时继续加,当解数为0时回溯

关于c# - 从数独解决方案中删除单元格使其成为一个谜题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14858994/

相关文章:

c# - 在 WP8 上更改按钮边框颜色时滞后

.net - 日语、中文和韩语等语言的 KeyUp/KeyDown 替代方案?

C# Windows 如何在检测到 .Net 版本后运行 exe

在许多字符串列表中查找相似字符串的算法

python - 在Python中使用完美压缩存储英式英语的一个字母所需的平均位数

c# - 如何使用 Silverlight 4 复制 DataGrid(包括 DataGridTemplateColumn)中所有单元格的选定内容?

c# - 通过异步示例了解 C# 中的并行编程

.net - 为什么我创建的新 WPF Windows 不是从 Window 继承的?

algorithm - 如果从通用哈希函数族中随机选择哈希函数,如何找到给定键的值?

c# - 如何将 IFormFile 保存到磁盘?