我正在编写一个Sudoku应用程序,目前正在开发游戏生成算法。我设法弄清楚如何快速生成解决方案(不解决)。不过,我对如何删除一些数字实际上将它变成一个谜题感到难过。我的第一个倾向是根据难度随机删除一定数量的单元格,但这不是正确的算法,因为它经常呈现无法解决的难题或具有多种解决方案。它也可能产生不能反映所要求的难度的谜题。
这是我到目前为止的代码。我删除了大部分不相关的代码,但如果你想看到一些未实现但在下面使用的内容,请告诉我。如果你愿意,我也可以尝试使用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);
}
}
}
我不是在寻找代码,而是在寻找算法。我如何从解决方案中删除数字以使其成为一个谜题?
答案 0 :(得分:2)
我认为您需要一个数独求解器,它还会计算可用解决方案的数量,然后以总是只有一个可用解决方案的方式减去数字。
您可以应用相同的方法向网格添加数字,然后检查可能的解决方案的数量,并在解决方案的数量大于1时继续添加,并在解决方案的数量为0时进行回溯
答案 1 :(得分:0)
没有“简单”的方法从已完成的数独网格中删除线索,因为删除过程不是线性的。
每次删除一个单元格或线索后,您需要检查Sudoku是否只有一个独特的解决方案。
要检查这一点,您需要运行一个可以计算所有可能解决方案的求解器(您可以在找到2种可能性后停止它)。
两个最流行的算法用于解决数独,计算所有数独解决方案和删除单元格是回溯算法和跳舞链接算法。
本文非常好地解释了如何在Sudokus中使用跳舞链接算法: 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