当前位置: 首页 > 知识库问答 >
问题:

从数独解决方案中删除单元格以使其成为谜题

贺劲
2023-03-14

我正在编写一个数独应用程序,目前正在研究游戏生成算法。我设法想出了如何快速生成解决方案(而不是解决方案)。然而,如何删除一些数字,使其真正成为一个谜,我感到困惑。我的第一个倾向是根据难度随机移除一定数量的单元格,但这不是正确的算法,因为它通常会呈现无法解决或有多个解决方案的谜题。它还可能生成无法反映所需难度的谜题。

这是我到目前为止拥有的代码。我删除了大部分不相关的代码,但如果您想看到下面未实现但使用的东西,请告诉我。如果您愿意,我也可以提供我对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);
        }
    }
}

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

共有2个答案

郑功
2023-03-14

没有“简单”的方法可以从已完成的数独网格中删除线索,因为删除过程不是线性的。

每次删除单元格或线索后,您需要检查数独是否只有唯一的解决方案。

要检查这一点,您需要运行一个可以计算所有可能解决方案的解算器(您可以在找到两种可能后停止它以节省时间)。

求解数独、计算所有数独解和删除单元格时最常用的两种算法是回溯算法和跳链算法。

这篇文章很好地解释了跳舞链接算法如何在数独中使用:http://garethrees.org/2007/06/10/zendoku-generation/#section-2

这是用JavaScript编写的Sudokus中跳舞链接算法的另一个描述:http://www.sudokubum.com/documentation.html

下面是关于舞蹈链接算法的全文:http://lanl.arxiv.org/pdf/cs/0011047

厉令
2023-03-14

这是一篇关于数独生成的论文

我认为你需要一个数独解算器,它也会计算出可用解的数量,然后以这样一种方式减去数字,即始终只有一个可用解。

您可以使用相同的方法向网格中添加数字,然后检查可能的解决方案的数量,并在解决方案数量大于1时继续添加,在解决方案数量为0时回溯

 类似资料:
  • 当不应显示视图时,删除单元格的自动布局约束的最佳方法是什么? 我们有一个单元格,它的布局大约有6-7个视图。其中一个视图是星级。当星级不可用时,我们不想显示视图。目前,我们隐藏视图,但这会保留自动布局约束。 类似的问题 - 当视图被隐藏时,如何使用自动布局来移动其他视图? 这就是上面提到的正在讨论的观点。当没有可用的星级评定时,我们希望从其超级视图中删除此视图。我们的问题是,如果我们从< code

  • 基于这个来自云平衡问题的示例,我尝试将客户从工作解决方案中删除,如下所示: 结果我得到了这个例外: java.lang.IllegalStateException:实体(Customer--6361356485874019865)有一个值为(Customer--902742678799526425)的变量(previousStandstill),该变量有一个值为(null)的sourceVaria

  • 我正在创建一个新的MVC4项目,研究使我相信现在通过web API框架而不是控制器操作更好地实现从javascript到服务器端的通信。我对此的理解是否正确? 我假定我可以在web API和MVC控制器之间共享我的所有属性等,所以从表面上看,这对我来说似乎并不是一个巨大的变化。 当我设置应用程序时,我喜欢将组件拆分到项目中。我的计划是有一个MVC项目和一个web API项目。但我遇到了一些问题。例

  • 我正在编写一个Android应用程序,从图片中提取数独谜题。对于9x9数独网格中的每个单元格,我需要确定它是包含数字1到9中的一个还是空白。以下是我的算法的大致要点: 自适应阈值拼图 扩展以减少要考虑的轮廓数 找到拼图的轮廓并将其扭曲成正方形 将正方形分成81个相等的单元格;寻找至少有20%白色像素的单元格 找到最靠近这些单元格中心的白色斑点并得到其边界矩形 对边界矩形内的图像部分使用字符识别(k

  • 我一直试图创建一个宏来格式化从特定外部源复制的表,问题是,一些单元格似乎从右向左填充,剩余的空间向左填充空格:

  • 问题内容: 起初,我使用了网格。创建新版本的GWT后,我想替换CellTable上的Grid。 问题答案: 查看javadoc以获取详细信息。我的示例就像您可以在此处找到的示例(稍稍扩展一下):