C# 整数[,]的数独求解算法
大家好 我一直在开发一个C#数独解算器应用程序,但我真诚地低估了求解数独的算法的难度。我一直在网上搜索我可以实现的算法,但我没有找到一个简单的算法,我可以让我的头脑 我发现了一个可能在我的应用程序中工作的算法,但是这个人正在使用一个一维数组来计算它。 我试图改变它,使其与多维数组一起工作,但无法使其正常工作 有谁能给我一些建议,或者告诉我如何修改代码,使其与多维数组(int[,])一起工作?我自己似乎找不到。代码可在此处找到: 如果你有另一个算法可以处理int[,],那当然也很好 我已经找了很长时间了,非常感谢您的帮助。C# 整数[,]的数独求解算法,c#,multidimensional-array,int,sudoku,solver,C#,Multidimensional Array,Int,Sudoku,Solver,大家好 我一直在开发一个C#数独解算器应用程序,但我真诚地低估了求解数独的算法的难度。我一直在网上搜索我可以实现的算法,但我没有找到一个简单的算法,我可以让我的头脑 我发现了一个可能在我的应用程序中工作的算法,但是这个人正在使用一个一维数组来计算它。 我试图改变它,使其与多维数组一起工作,但无法使其正常工作 有谁能给我一些建议,或者告诉我如何修改代码,使其与多维数组(int[,])一起工作?我自己似乎找不到。代码可在此处找到: 如果你有另一个算法可以处理int[,],那当然也很好 我已经找了很长
提前谢谢 您链接的代码在逻辑上已经使用了2D数组,它只使用1D数组作为支持。更改此项:
private int[] vals = new int[81];
public int this[int row, int column]
{
get { return vals[FindIndex(row, column)]; }
set
{
vals[FindIndex(row, column)] = value;
}
}
private int FindIndex(int row, int column)
{
return (((column - 1) * 9) + row - 1);
}
致:
(当前代码的其余部分需要
-1
,因为行和列从1开始,而不是从0开始。)递归回溯、暴力、算法
public class SudokoSolver
{
private readonly Grid _grid;
public SudokoSolver(Grid grid)
{
_grid = grid;
_grid.Validate();
}
public int?[,] SolvePuzzle()
{
Solve();
Console.WriteLine(_grid.Assigns + " tries total.");
return _grid.Data;
}
private bool Solve()
{
int row, col;
if (!_grid.FindUnassignedLoc(out row, out col))
{
return true;
}
for (int num = 1; num <= 9; num++)
{
if (_grid.NoConflicts(row, col, num))
{
_grid.Assign(row, col, num);
if (Solve())
{
return true;
}
_grid.Unassign(row, col);
}
}
return false;
}
public int?[,] Data
{
get { return _grid.Data; }
}
}
public class Grid
{
public int?[,] Data { get; private set; }
private int _curC = 0;
private int _curR = 0;
private int _assigns = 0;
public Grid(int?[,] data)
{
Data = data ?? new int?[9,9];
}
public bool FindUnassignedLoc(out int row, out int col)
{
while (Data[_curR, _curC].HasValue)
{
_curC++;
if (_curC == 9)
{
_curR++;
_curC = 0;
}
if (_curR == 9)
{
row = -1;
col = -1;
return false;
}
}
row = _curR;
col = _curC;
return true;
}
public bool NoConflicts(int row, int col, int num)
{
for (int r = 0; r < 9; ++r)
{
if (Data[r, col] == num)
{
return false;
}
}
for (int c = 0; c < 9; c++)
{
if (Data[row, c] == num)
{
return false;
}
}
int fromC = 3 * (col/3);
int fromR = 3 * (row / 3);
for (int c = fromC; c < fromC + 3; c++)
{
for (int r = fromR; r < fromR + 3; r++)
{
if (Data[r, c] == num)
{
return false;
}
}
}
return true;
}
public void Assign(int row, int col, int num)
{
_assigns++;
Data[row, col] = num;
}
public void Unassign(int row, int col)
{
Data[row, col] = null;
_curC = col;
_curR = row;
}
public int Assigns
{
get { return _assigns; }
}
public void Validate()
{
if (Data.Length != 81)
{
throw new Exception("Invalid dimentions!");
}
if (!IsLegal())
{
throw new Exception("Illigal numbers populated!");
}
}
public bool IsLegal()
{
var container = new HashSet<int>();
//vertical check
for (int c = 0; c < 9; ++c)
{
container.Clear();
for (int r = 0; r < 9; ++r)
{
if (Data[r, c].HasValue)
{
if (container.Contains(Data[r, c].Value))
{
return false;
}
container.Add(Data[r, c].Value);
}
}
}
// horizontal check
for (int r = 0; r < 9; ++r)
{
container.Clear();
for (int c = 0; c < 9; ++c)
{
if (Data[r, c].HasValue)
{
if (container.Contains(Data[r, c].Value))
{
return false;
}
container.Add(Data[r, c].Value);
}
}
}
// square check
var topLeftCorners = new List<Tuple<int, int>>
{
new Tuple<int, int>(0,0),
new Tuple<int, int>(0,3),
new Tuple<int, int>(0,6),
new Tuple<int, int>(3,0),
new Tuple<int, int>(3,3),
new Tuple<int, int>(3,6),
new Tuple<int, int>(6,0),
new Tuple<int, int>(6,3),
new Tuple<int, int>(6,6)
};
foreach (var topLeftCorner in topLeftCorners)
{
int fromC = topLeftCorner.Item2;
int fromR = topLeftCorner.Item1;
container.Clear();
for (int c = fromC; c < fromC + 3; c++)
{
for (int r = fromR; r < fromR + 3; r++)
{
if (Data[r, c].HasValue)
{
if (container.Contains(Data[r, c].Value))
{
return false;
}
container.Add(Data[r, c].Value);
}
}
}
}
return true;
}
}
公共级SudokoSolver
{
专用只读网格_网格;
公共SudokoSolver(网格)
{
_网格=网格;
_grid.Validate();
}
公共整数?[,]SolvePuzzle()
{
Solve();
Console.WriteLine(_grid.Assigns+“trys total”);
返回_grid.Data;
}
私有布尔解算()
{
int row,col;
如果(!\u网格findunsignedloc(行外、列外))
{
返回true;
}
对于(int num=1;num然后编写一个方法,将2d数组更改为1d,并使用该代码。解数独的算法?我所做的只是教我的计算机数独规则,然后使用蛮力,哈哈。是的,但我还不够聪明,无法创建这样的东西。你看,我是一个相当初级的程序员:).我甚至在努力用Tim的想法实现我想要的。你应该阅读我关于C#的简单图形着色算法的系列文章。系列的最后一集对你特别感兴趣,但从一开始就开始。你是对的,它实际上使用了一个逻辑2D数组。我将尝试你的方法,谢谢你的帮助!请e解释你问题的细节。强力算法,带回溯。从(0,0)->(0,1)->(0,2)开始分配,直到全部填满。如果在某一点上,选项用尽,回溯到上一个分配,等等。。
public class SudokoSolver
{
private readonly Grid _grid;
public SudokoSolver(Grid grid)
{
_grid = grid;
_grid.Validate();
}
public int?[,] SolvePuzzle()
{
Solve();
Console.WriteLine(_grid.Assigns + " tries total.");
return _grid.Data;
}
private bool Solve()
{
int row, col;
if (!_grid.FindUnassignedLoc(out row, out col))
{
return true;
}
for (int num = 1; num <= 9; num++)
{
if (_grid.NoConflicts(row, col, num))
{
_grid.Assign(row, col, num);
if (Solve())
{
return true;
}
_grid.Unassign(row, col);
}
}
return false;
}
public int?[,] Data
{
get { return _grid.Data; }
}
}
public class Grid
{
public int?[,] Data { get; private set; }
private int _curC = 0;
private int _curR = 0;
private int _assigns = 0;
public Grid(int?[,] data)
{
Data = data ?? new int?[9,9];
}
public bool FindUnassignedLoc(out int row, out int col)
{
while (Data[_curR, _curC].HasValue)
{
_curC++;
if (_curC == 9)
{
_curR++;
_curC = 0;
}
if (_curR == 9)
{
row = -1;
col = -1;
return false;
}
}
row = _curR;
col = _curC;
return true;
}
public bool NoConflicts(int row, int col, int num)
{
for (int r = 0; r < 9; ++r)
{
if (Data[r, col] == num)
{
return false;
}
}
for (int c = 0; c < 9; c++)
{
if (Data[row, c] == num)
{
return false;
}
}
int fromC = 3 * (col/3);
int fromR = 3 * (row / 3);
for (int c = fromC; c < fromC + 3; c++)
{
for (int r = fromR; r < fromR + 3; r++)
{
if (Data[r, c] == num)
{
return false;
}
}
}
return true;
}
public void Assign(int row, int col, int num)
{
_assigns++;
Data[row, col] = num;
}
public void Unassign(int row, int col)
{
Data[row, col] = null;
_curC = col;
_curR = row;
}
public int Assigns
{
get { return _assigns; }
}
public void Validate()
{
if (Data.Length != 81)
{
throw new Exception("Invalid dimentions!");
}
if (!IsLegal())
{
throw new Exception("Illigal numbers populated!");
}
}
public bool IsLegal()
{
var container = new HashSet<int>();
//vertical check
for (int c = 0; c < 9; ++c)
{
container.Clear();
for (int r = 0; r < 9; ++r)
{
if (Data[r, c].HasValue)
{
if (container.Contains(Data[r, c].Value))
{
return false;
}
container.Add(Data[r, c].Value);
}
}
}
// horizontal check
for (int r = 0; r < 9; ++r)
{
container.Clear();
for (int c = 0; c < 9; ++c)
{
if (Data[r, c].HasValue)
{
if (container.Contains(Data[r, c].Value))
{
return false;
}
container.Add(Data[r, c].Value);
}
}
}
// square check
var topLeftCorners = new List<Tuple<int, int>>
{
new Tuple<int, int>(0,0),
new Tuple<int, int>(0,3),
new Tuple<int, int>(0,6),
new Tuple<int, int>(3,0),
new Tuple<int, int>(3,3),
new Tuple<int, int>(3,6),
new Tuple<int, int>(6,0),
new Tuple<int, int>(6,3),
new Tuple<int, int>(6,6)
};
foreach (var topLeftCorner in topLeftCorners)
{
int fromC = topLeftCorner.Item2;
int fromR = topLeftCorner.Item1;
container.Clear();
for (int c = fromC; c < fromC + 3; c++)
{
for (int r = fromR; r < fromR + 3; r++)
{
if (Data[r, c].HasValue)
{
if (container.Contains(Data[r, c].Value))
{
return false;
}
container.Add(Data[r, c].Value);
}
}
}
}
return true;
}
}