[英]How do I fix my stack overflow error for Sudoku solver c#? Has to do with Recursive function?
[英]Why is my sudoku solver in C# not working?
這是我的第一篇文章,如果我做錯了,我深表歉意。 幾個月前我開始在 python 編碼,現在我已經轉向 C#。 為了學習回溯,我嘗試編寫數獨求解器。 但是,對於我的一生,我無法理解為什么我的代碼不起作用。 當然,有很多解決方案。 我覺得我現在進步的最好方法是了解我在我的個人代碼中缺少什么。 所以,如果你有時間:
為什么我的代碼不會返回一個已解決的數獨板? 我懷疑錯誤在於遞歸。
主程序:
using System;
namespace Sudoku
{
class Program
{
static void Main(string[] args)
{
var sudokuTemplate = new SudokuTemplate();
var sudoku = sudokuTemplate.CreateSudoku();
Print.print(sudoku);
Console.WriteLine();
Print.print(driver(sudoku));
}
static int[,] driver(int[,] board)
{
var check = new ErrorCheck();
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
if (board[i,j] == 0)
{
for (int n = 1; n <= 9; n++)
{
if (check.legal(board, i, j, n))
{
board[i, j] = n;
driver(board);
}
else
{
board[i, j] = 0;
}
}
return board;
}
}
}
return board;
}
}
}
未解的數獨
namespace Sudoku
{
class SudokuTemplate
{
public int[,] CreateSudoku()
{
var array = new int[,]
{
{5,3,0,0,7,0,0,0,0},
{6,0,0,1,9,5,0,0,0},
{0,9,8,0,0,0,0,6,0},
{8,0,0,0,6,0,0,0,3},
{4,0,0,8,0,3,0,0,1},
{7,0,0,0,2,0,0,0,6},
{0,6,0,0,0,0,2,8,0},
{0,0,0,4,1,9,0,0,5},
{0,0,0,0,8,0,0,7,9}
};
return array;
}
}
}
錯誤檢查器查看數字 n 是否可以合法放置在板上:
namespace Sudoku
{
public class ErrorCheck
{
public bool legal(int[,]array, int row, int col, int n)
{ //check col & rw
for (int i = 0; i < 9; i++)
{
if (array[row, i] == n)
{
return false;
}
if (array[i, col] == n)
{
return false;
}
}
//check boxes
int valRow = 0;
if (row < 6 && row > 2)
{
valRow = 3;
}
else if (row < 9 && row > 5)
{
valRow = 6;
}
int valCol = 0;
if (col < 6 && col > 2)
{
valCol = 3;
}
else if (col < 9 && col > 5)
{
valCol = 6;
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (array[(j+valRow), (i+valCol)] == n)
{
return false;
}
}
}
return true;
}
}
}
最后打印 function:
namespace Sudoku
{
class Print
{
public static void print(int[,] array)
{
// prints sudoku
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
Console.Write("{0} ", array[i, j]);
Console.Write("|");
}
Console.WriteLine();
}
}
}
}
編輯:
代碼導致打印原始未解決的數獨板兩次。 它最初似乎工作正常,但在某個地方,一切都只是重置為原始未解決的板。
存在三個問題。
第一個是在 sgmoore 的回答中,數獨是無效的。 嘗試從互聯網復制現有的數獨。
第二個是在 ErrorCheck class 中:
if (array[(i+valCol), (j+valRow)] == n)
您必須反轉矩陣的兩個索引才能獲得正確的框。
if (array[(j+valRow), (i+valCol)] == n)
第三個錯誤出現在程序 class 中:您在單元格中輸入了第一個有效數字。 在數獨中,您必須輸入唯一有效的數字。 因此,在我看來,對於每個單元格,您必須檢查所有九個數字並將所有可能的值保存在一個列表中,然后如果只有一個可能的值,則將其放入。 這種方法對於簡單的數獨來說已經足夠了,但如果復雜度增加,您將不得不使用其他高級技術,例如雙對或 X-Wing。
除了錯誤,我認為您的代碼非常清晰易讀。 我要做的唯一更改是在程序 class 中用“row”和“col”重命名“i”和“j”。
謝謝大家的回復。 正如 Astrid 所建議的,我在調試器中花費了更多時間並修復了一堆邏輯錯誤。 我搞混了|| 以 && 為例(我認為這些錯誤現在已被刪除)。 盡管如此,這還不足以讓代碼正常工作。 因此,我將回溯移出驅動程序 function 中的 for 循環。 這是因為我想象該方法可能正在完成它的工作,並且只是在它出現時用 0 重寫所有內容。 更改后,它看起來像這樣:
static int[,] driver(int[,] board)
{
var check = new ErrorCheck();
for (int row = 0; row < 9; row++)
{
for (int col = 0; col < 9; col++)
{
if (board[row, col] == 0)
{
for (int n = 1; n <= 9; n++)
{
if (check.legal(board, row, col, n))
{
board[row, col] = n;
driver(board);
}
}
board[row, col] = 0;
return board;
}
}
}
return board;
}
盡管如此,它還是沒有奏效。 我嘗試通過打印控制台發生的事情來進行調試。 有時,根本沒有打印任何東西。 最后,我嘗試從方法和 BAM 中打印。 它似乎奏效了。
static int[,] driver(int[,] board)
{
var check = new ErrorCheck();
for (int row = 0; row < 9; row++)
{
for (int col = 0; col < 9; col++)
{
if (board[row, col] == 0)
{
for (int n = 1; n <= 9; n++)
{
if (check.legal(board, row, col, n))
{
board[row, col] = n;
driver(board);
}
}
board[row, col] = 0;
return board;
}
}
}
Print.print(board);
return board;
}
我沒有按照 Samuele Coassin 的建議實現花哨的優化,但至少可以。 但是,我不知道為什么 Print.print() 方法不能在驅動程序方法之外工作。 如果有人有線索,請隨時回復。 如果沒有,無論如何感謝您對您表現出的興趣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.