Golang 数独算法不起作用
Golang sudoku algorithm not working
我是 Golang 的新手,我正在尝试用回溯算法做一个数独游戏。
但是当我 运行 我的程序时,没有错误,但它只显示网格不完整,空的情况下这是我的代码:
package main
import "fmt"
var sudoku = [9][9]int{
{9, 0, 0, 1, 0, 0, 0, 0, 5},
{0, 0, 5, 0, 9, 0, 2, 0, 1},
{8, 0, 0, 0, 4, 0, 0, 0, 0},
{0, 0, 0, 0, 8, 0, 0, 0, 0},
{0, 0, 0, 7, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 2, 6, 0, 0, 9},
{2, 0, 0, 3, 0, 0, 0, 0, 6},
{0, 0, 0, 2, 0, 0, 9, 0, 0},
{0, 0, 1, 9, 0, 4, 5, 7, 0},
}
func main(){
IsValid(sudoku, 0)
Display(sudoku)
}
func Display(sudoku[9][9] int){
var x, y int
for x = 0; x < 9; x++ {
fmt.Println("")
if(x == 3 || x == 6){
fmt.Println(" ")
}
for y = 0; y < 9; y++ {
if(y == 3 || y == 6){
fmt.Print("|")
}
fmt.Print(sudoku[x][y])
}
}
}
func AbsentOnLine(k int, sudoku [9][9]int, x int) bool {
var y int
for y=0; y < 9; y++ {
if (sudoku[x][y] == k){
return false
}
}
return true
}
func AbsentOnRow(k int, sudoku [9][9]int, y int) bool {
var x int
for x=0; x < 9; x++{
if (sudoku[x][y] == k){
return false;
}
}
return true;
}
func AbsentOnBloc(k int, sudoku [9][9]int, x int, y int) bool {
var firstX, firstY int;
firstX = x-(x%3)
firstY = y-(y%3)
for x = firstX; x < firstX+3; x++ {
for y = firstY; y < firstY+3; y++ {
if (sudoku[x][y] == k){
return false;
}
}
}
return true;
}
func IsValid(sudoku [9][9]int, position int) bool {
if (position == 9*9){
return true;
}
var x, y, k int
x = position/9
y = position%9
if (sudoku[x][y] != 0){
return IsValid(sudoku, position+1);
}
for k=1; k <= 9; k++ {
if (AbsentOnLine(k,sudoku,x) && AbsentOnRow(k,sudoku,y) && AbsentOnBloc(k,sudoku,x,y)){
sudoku[x][y] = k;
if (IsValid(sudoku, position+1)){
return true;
}
}
}
sudoku[x][y] = 0;
return false;
}
我在控制台中得到这个:
900|100|005
005|090|201
800|040|000
000|080|000
000|700|000
000|026|009
200|300|006
000|200|900
001|904|570
我不明白为什么它没有完成网格,有没有人有什么想法?
我不会Golang,但是我写了一个使用回溯法的数独解法
你的代码只迭代一次棋盘。你从 position=0
开始,你的代码会迭代棋盘,如果一个位置的值为零,你尝试值1-9,如果这不起作用,则转到下一个位置。当 position=81
时,您的代码停止。
您使用 Isvalid
函数向面板添加了新值,但您没有再次迭代新面板以查看这些新值是否有助于您的 AbsentOn...
函数达到 return 与上一次迭代不同的新值。您必须一次又一次地迭代您的电路板,直到您确定没有 0
个有价值的单元格。
这就是为什么你在程序结束时必须在板上有很多 0
的原因。您的程序仅迭代一次,在第一次尝试时无法解决您的示例数独问题。它必须向棋盘添加新的值,并在每次迭代中使数独棋盘更容易。
另一个问题是您的代码没有给出反馈。例如,它将 1
赋给一个空单元格。乍一看这似乎没问题,但这并不意味着该单元格的最终值必须是 1
。它可能会改变,因为在你的下一次迭代中你意识到有另一个单元格只能取值 1
,所以现在你必须改回你的初始单元格并找到一个新值而不是 1
.您的代码也无法做到这一点。这就是为什么人们在不确定时会在单元格附近放置一些可能的值。
看来你的问题出在算法上。您必须了解回溯算法。您可以先用另一种您熟悉的语言尝试它,然后将其迁移到 golang(我用 C++ 编写我的)。除此之外,您的 golang 代码易于阅读,我没有看到任何与 golang 相关的问题。
您的 IsValid
函数更改了数独的内容。问题是,它实际上在您的代码中只更改了数独的 copy。如果它应该更改实际变量,则需要将其作为指针传递。
以下是您需要在代码中进行的更改,只有五个字符:
func main() {
IsValid(&sudoku, 0)
Display(sudoku)
}
// ...
func IsValid(sudoku *[9][9]int, position int) bool {
// ...
if AbsentOnLine(k, *sudoku, x) && AbsentOnRow(k, *sudoku, y) && AbsentOnBloc(k, *sudoku, x, y) {
我是 Golang 的新手,我正在尝试用回溯算法做一个数独游戏。 但是当我 运行 我的程序时,没有错误,但它只显示网格不完整,空的情况下这是我的代码:
package main
import "fmt"
var sudoku = [9][9]int{
{9, 0, 0, 1, 0, 0, 0, 0, 5},
{0, 0, 5, 0, 9, 0, 2, 0, 1},
{8, 0, 0, 0, 4, 0, 0, 0, 0},
{0, 0, 0, 0, 8, 0, 0, 0, 0},
{0, 0, 0, 7, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 2, 6, 0, 0, 9},
{2, 0, 0, 3, 0, 0, 0, 0, 6},
{0, 0, 0, 2, 0, 0, 9, 0, 0},
{0, 0, 1, 9, 0, 4, 5, 7, 0},
}
func main(){
IsValid(sudoku, 0)
Display(sudoku)
}
func Display(sudoku[9][9] int){
var x, y int
for x = 0; x < 9; x++ {
fmt.Println("")
if(x == 3 || x == 6){
fmt.Println(" ")
}
for y = 0; y < 9; y++ {
if(y == 3 || y == 6){
fmt.Print("|")
}
fmt.Print(sudoku[x][y])
}
}
}
func AbsentOnLine(k int, sudoku [9][9]int, x int) bool {
var y int
for y=0; y < 9; y++ {
if (sudoku[x][y] == k){
return false
}
}
return true
}
func AbsentOnRow(k int, sudoku [9][9]int, y int) bool {
var x int
for x=0; x < 9; x++{
if (sudoku[x][y] == k){
return false;
}
}
return true;
}
func AbsentOnBloc(k int, sudoku [9][9]int, x int, y int) bool {
var firstX, firstY int;
firstX = x-(x%3)
firstY = y-(y%3)
for x = firstX; x < firstX+3; x++ {
for y = firstY; y < firstY+3; y++ {
if (sudoku[x][y] == k){
return false;
}
}
}
return true;
}
func IsValid(sudoku [9][9]int, position int) bool {
if (position == 9*9){
return true;
}
var x, y, k int
x = position/9
y = position%9
if (sudoku[x][y] != 0){
return IsValid(sudoku, position+1);
}
for k=1; k <= 9; k++ {
if (AbsentOnLine(k,sudoku,x) && AbsentOnRow(k,sudoku,y) && AbsentOnBloc(k,sudoku,x,y)){
sudoku[x][y] = k;
if (IsValid(sudoku, position+1)){
return true;
}
}
}
sudoku[x][y] = 0;
return false;
}
我在控制台中得到这个:
900|100|005
005|090|201
800|040|000
000|080|000
000|700|000
000|026|009
200|300|006
000|200|900
001|904|570
我不明白为什么它没有完成网格,有没有人有什么想法?
我不会Golang,但是我写了一个使用回溯法的数独解法
你的代码只迭代一次棋盘。你从 position=0
开始,你的代码会迭代棋盘,如果一个位置的值为零,你尝试值1-9,如果这不起作用,则转到下一个位置。当 position=81
时,您的代码停止。
您使用 Isvalid
函数向面板添加了新值,但您没有再次迭代新面板以查看这些新值是否有助于您的 AbsentOn...
函数达到 return 与上一次迭代不同的新值。您必须一次又一次地迭代您的电路板,直到您确定没有 0
个有价值的单元格。
这就是为什么你在程序结束时必须在板上有很多 0
的原因。您的程序仅迭代一次,在第一次尝试时无法解决您的示例数独问题。它必须向棋盘添加新的值,并在每次迭代中使数独棋盘更容易。
另一个问题是您的代码没有给出反馈。例如,它将 1
赋给一个空单元格。乍一看这似乎没问题,但这并不意味着该单元格的最终值必须是 1
。它可能会改变,因为在你的下一次迭代中你意识到有另一个单元格只能取值 1
,所以现在你必须改回你的初始单元格并找到一个新值而不是 1
.您的代码也无法做到这一点。这就是为什么人们在不确定时会在单元格附近放置一些可能的值。
看来你的问题出在算法上。您必须了解回溯算法。您可以先用另一种您熟悉的语言尝试它,然后将其迁移到 golang(我用 C++ 编写我的)。除此之外,您的 golang 代码易于阅读,我没有看到任何与 golang 相关的问题。
您的 IsValid
函数更改了数独的内容。问题是,它实际上在您的代码中只更改了数独的 copy。如果它应该更改实际变量,则需要将其作为指针传递。
以下是您需要在代码中进行的更改,只有五个字符:
func main() {
IsValid(&sudoku, 0)
Display(sudoku)
}
// ...
func IsValid(sudoku *[9][9]int, position int) bool {
// ...
if AbsentOnLine(k, *sudoku, x) && AbsentOnRow(k, *sudoku, y) && AbsentOnBloc(k, *sudoku, x, y) {