我创建了一个Sudoku
Backtracking解算器,并且效果很好,但是现在我想给出一个错误,如果该数独无法解决,因为它是无效的,例如如果给出了这个数独:
http://img5.imageshack.us/img5/2241/sudokugq.jpg
如果无法解决,我该怎么办才能使我的解决方法出错?我总是以零结束或陷入循环。
public void solve( int row, int col ) throws Exception
{
// Throw an exception to stop the process if the puzzle is solved
if( row > 8 ){
//Gelöst
}
// If the cell is not empty, continue with the next cell
if( sudo[row][col] != 0 ){
next( row, col ) ;
}
else
{
// Find a valid number for the empty cell
for( int num = 1; num < 10; num++ )
{
if( checkHorizontal(row,num) == false && checkVertikal(col,num)== false&& checkBox(row,col,num)== false )
{
sudo[row][col] = num ;
// Delegate work on the next cell to a resudosive call
next( row, col ) ;
}
}
// No valid number was found, clean up and return to caller
sudo[row][col] = 0 ;
}
}
//Ruft solve für das nächste Feld auf
public void next( int row, int col ) throws Exception
{
if( col < 8 )
solve( row, col + 1 ) ;
else
solve( row + 1, 0 ) ;
}
当然,当您触及sudo[row][col] = 0 ;
代码时,您刚刚尝试了平方中的每个值,但找不到任何解决方案。当然,这是您决定放弃无解决方案状态的关键所在。
进一步考虑-我怀疑我几乎是正确的。如果您遇到此代码, 并且 这是您尝试的 第一个 单元(即找到的第一个空单元),那么这就是您的失败时刻。
顺便说一句-我不确定使用Exception来指示您在注释中建议的解决方案是一个好主意。
现在,这可以正确地拒绝您发布的木板-请注意,第一行不仅有两个“ 3”,而且在第一列中也有两个“
5”。该代码现在似乎对我有用。也许您可以在一个无法解决的问题上尝试一下。
public class Test {
static final int S = 9;
int[][] sudo;
public Test() {
// Just leave it empty.
sudo = new int[S][S];
}
public Test(int[][] sudo) {
this.sudo = sudo;
}
// This number should not appear anywhere in the row.
public boolean checkHorizontal(int row, int num) {
for (int i = 0; i < S; i++) {
if (sudo[row][i] == num) {
return false;
}
}
return true;
}
// This number should not appear anywhere in the col.
public boolean checkVertical(int col, int num) {
for (int i = 0; i < S; i++) {
if (sudo[i][col] == num) {
return false;
}
}
return true;
}
// This number should not appear anywhere in the box.
private boolean checkBox(int row, int col, int num) {
// Round down to nearest 3.
int r = (row / 3) * 3;
int c = (col / 3) * 3;
for (int i = r; i < r + 3; i++) {
for (int j = c; j < c + 3; j++) {
if (sudo[i][j] == num) {
return false;
}
}
}
return true;
}
boolean check(int row, int col, int num) {
// All checks must pass.
return checkHorizontal(row, num)
&& checkVertical(col, num)
&& checkBox(row, col, num);
}
public boolean solve(int row, int col) {
// Got to the end?
if (row >= S) {
//Gelöst
return true;
}
// If the cell is empty
if (sudo[row][col] == 0) {
// Find a valid number for the empty cell
for (int num = 1; num < 10; num++) {
// Can this number be put there?
if (check(row, col, num)) {
// Yes!
sudo[row][col] = num;
// Try that.
if (next(row, col)) {
return true;
}
}
}
// Clean up.
sudo[row][col] = 0;
} else {
// Move on.
if (next(row, col)) {
return true;
}
}
// Failed to find a solution.
return false;
}
//Ruft solve für das nächste Feld auf
public boolean next(int row, int col) {
if (col < S - 1) {
// Step right.
return solve(row, col + 1);
} else {
// Step down.
return solve(row + 1, 0);
}
}
public boolean boardOk() {
// Initial test to ensure it is a valid array.
// Must have that many rows.
boolean ok = sudo.length == S;
for (int row = 0; ok && row < S; row++) {
// Each row must be that long.
ok &= sudo[row].length == S;
for (int col = 0; ok && col < S; col++) {
// Each filled square must be valid.
if (sudo[row][col] != 0) {
int num = sudo[row][col];
// Remove it.
sudo[row][col] = 0;
// Check it can be added.
ok &= check(row, col, num);
// Put it back.
sudo[row][col] = num;
}
}
}
return ok;
}
void solve() {
if (boardOk()) {
boolean solved = solve(0, 0);
if (solved) {
System.out.println("Solved!");
print();
}
} else {
System.out.println("Insoluble!");
print();
}
}
public void print() {
for (int i = 0; i < sudo.length; i++) {
System.out.println(Arrays.toString(sudo[i]));
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
new Test().solve();
int[][] test = {
{0, 0, 6, 5, 8, 3, 3, 2, 7},
{0, 0, 0, 0, 9, 0, 0, 5, 0},
{5, 8, 0, 0, 0, 0, 0, 0, 3},
{0, 3, 1, 0, 4, 0, 5, 0, 0},
{0, 0, 0, 9, 2, 0, 3, 0, 6},
{0, 0, 0, 0, 0, 0, 0, 0, 1},
{3, 4, 2, 0, 0, 6, 9, 1, 5},
{5, 0, 5, 4, 0, 9, 0, 3, 2},
{0, 1, 0, 0, 0, 0, 0, 0, 4},};
new Test(test).solve();
}
}
我对编码还是很陌生的,我正在尝试一些稍微困难的主题,例如修改数独递归回溯程序的解决方案。最初的解决方案是针对大小为3x3的数独,我希望我的解决方案可以与正常大小的数独(9x9)一起使用。3x3解决方案在这里找到。 我觉得我对算法非常了解:对于网格中的每个列表(包含该单元格的可能值),在每一步尝试每个数字,确保电路板仍然有效,移动到下一个列表,分配一个可能的数字直到其有效,等等。如果当前电路板不正确
我的问题是,当一个9不能正确添加时,该方法会中断。不知何故,我不知道如何让它回到前一点,并向上数,这将创建一个新的“路径”,所以我想如果我做对了,一切都应该很好。我仍然在使用递归:-/ 正如我所知,我认为Sudokurecrect()做了它应该做的事情。编辑:您可以忽略布尔测试。我知道我不使用它,我试着想一些东西,但显然我不知道如何使用它。 输出为 在那之后,不管检查哪个变体。所以问题是一样的。
我已经创建了一个数独解算器,它可以像人类一样解数独,通过检查与被检查方格对应的方格中的可能性确定值。 (来源:http://pastebin.com/KVrXUDBF) 但是,我想创建一个随机数独生成器(从空白网格),因此决定使用回溯算法。我理解回溯的概念,但对一件事感到困惑: 一旦我知道某个解决方案是不允许的,我如何知道要返回(和更改)哪个前一个节点?我应该简单地返回到前一个节点并循环浏览所有可
我试图使用回溯在JavaScript中创建一个数独求解器,我做了一些研究,看到了类似的问题,但我的方法不同;而且没用。 使用它,浏览器停止响应,然后询问是否停止脚本。 在控制台中,我得到: 有什么问题的线索吗?
我已经在这里寻求帮助,但没有人回答,这真的很令人沮丧,我试图写一个代码,解决递归函数中的数独(回溯),下面是代码: 它不是真正的代码(只是因为UI现在不重要)。所以我在这里所做的是,每次它改变任何单元格时,都打印板子。当它试图解决一个错误时,我看到了一个错误,当它到达第2行col:6单元格(在索引its[1][5])时,它跳过了数字1(这是真正的答案),因为它没有尝试一个,它不能解决数独的其余部分
我正在做一个小的个人数独游戏,并试图扩展它。 到目前为止,我使用递归回溯方法使“Solve”部分正常工作,每当它设法解决递归时,就会返回true。 现在我正在尝试构建一个独特的解决方案板生成器,我在网上找到了很多关于如何实现它的信息。 然而,我在第一步很挣扎,这是我的布尔递归回溯算法变成一个递归算法,它保留了一个可能解决方案的计数。这对于检查我生成的板是否是唯一的至关重要。 更重要的是,我意识到我