回复 39# happytc
正如happytc兄所说,29楼的代码如果是给出全0的数,猜数独的话,是可以出全排列的.
这也就解释了为何如happytc兄所举的例子中Local $array[9][9] = [[0, 6, 1, 0, 3, 0, 0, 2, 0], _
[0, 5, 0, 0, 0, 8, 1, 0, 7], _
[0, 0, 0, 0, 0, 7, 0, 3, 4], _
[0, 0, 9, 0, 0, 6, 0, 7, 8], _
[0, 0, 3, 2, 0, 9, 5, 0, 0], _
[5, 7, 0, 3, 0, 0, 9, 0, 0], _
[1, 9, 0, 7, 0, 0, 0, 0, 0], _
[8, 0, 2, 4, 0, 0, 0, 0, 0], _
[0, 4, 0, 0, 1, 0, 2, 5, 0]]
第[8][8]中的6挖去我的代码会出现死循环的结果.
happytc兄的代码是猜数,我的代码是去除不可能的数,happytc兄的代码设计想法非常先进,让人非常佩服.
虽然如此,但还是给出我在6楼代码中的修正代码,仅仅作为论坛留档,避免本地硬盘中文件管理混乱.
#include <array.au3>
$time = TimerInit()
Global $flag_W = 1
Local $k = "1234567890"
;~ Local $array[9][9] = [[0, 6, 1, 0, 3, 0, 0, 2, 0],[0, 5, 0, 0, 0, 8, 1, 0, 7],[0, 0, 0, 0, 0, 7, 0, 3, 4],[0, 0, 9, 0, 0, 6, 0, 7, 8],[0, 0, 3, 2, 0, 9, 5, 0, 0],[5, 7, 0, 3, 0, 0, 9, 0, 0],[1, 9, 0, 7, 0, 0, 0, 0, 0],[8, 0, 2, 4, 0, 0, 0, 6, 0],[0, 4, 0, 0, 1, 0, 2, 5, 0]]
Local $array[9][9] = [[0, 6, 0, 0, 4, 0, 9, 0, 3], _
[0, 7, 0, 0, 8, 5, 0, 1, 0], _
[4,0,1,7,0,0,0,0,2], _
[0,9,0,0,5, 0, 0, 6,4], _
[0, 4, 0, 8, 9, 0, 0, 5, 0], _
[1, 8, 0, 0, 0, 4, 0, 9, 0], _
[3, 0, 0, 0, 0, 8, 7, 0, 5], _
[0, 1, 0, 5, 7, 0, 0, 2, 0], _
[7, 0, 9, 0, 2, 0, 0, 3, 0]]
$abc = sudoku($array)
_ArrayDisplay($abc, TimerDiff($time))
Func sudoku($array)
Local $str
For $i = 0 To 8;初始化
For $n = 0 To 8
$str &= $array[$i][$n] & "|"
Next
$str_1 = StringRegExpReplace($k, $str, '')
$str = ""
For $n = 0 To 8
If $array[$i][$n] = 0 Then $array[$i][$n] = $str_1
Next
$str_1 = ""
Next
;~ _ArrayDisplay($array)
While 1
;去除行重复
For $i = 0 To 8
Local $str = '', $aabb = ""
For $n = 0 To 8
If StringLen($array[$i][$n]) = 1 Then
$str &= $array[$i][$n] & "|"
EndIf
$aabb &= $array[$i][$n] & "|"
Next
For $n = 0 To 8
If StringLen($array[$i][$n]) > 1 Then
$array[$i][$n] = StringRegExpReplace($array[$i][$n], $str, '')
EndIf
Next
Local $fl[1] = [0]
For $o = 1 To 9
$min = StringRegExp($aabb, $o, 3)
If UBound($min) = 1 Then
_ArrayAdd($fl, $o)
EndIf
Next
For $n = 0 To 8
For $c = 1 To UBound($fl) - 1
If StringInStr($array[$i][$n], $fl[$c]) Then $array[$i][$n] = $fl[$c]
Next
Next
Next
;以下去除列重复
For $i = 0 To 8
Local $str = ''
For $n = 0 To 8
If StringLen($array[$n][$i]) = 1 Then
$str &= $array[$n][$i] & "|"
EndIf
Next
For $n = 0 To 8
If StringLen($array[$n][$i]) > 1 Then
$array[$n][$i] = StringRegExpReplace($array[$n][$i], $str, '')
EndIf
Next
Next
;去除九宫重复
For $i = 0 To 8 Step 3
For $n = 0 To 8 Step 3
Local $temp[3][3], $sp = '', $aabb = ""
For $a = 0 To 2
For $b = 0 To 2
If StringLen($array[$a + $i][$b + $n]) = 1 Then $sp &= $array[$a + $i][$b + $n]
Next
Next
For $a = 0 To 2
For $b = 0 To 2
If StringLen($array[$a + $i][$b + $n]) > 1 Then $array[$a + $i][$b + $n] = StringRegExpReplace($array[$a + $i][$b + $n], '[' & $sp & ']', '')
$aabb &= $array[$a + $i][$b + $n] & "|"
Next
Next
Local $fl[1] = [0]
For $o = 1 To 9
$min = StringRegExp($aabb, $o, 3)
If UBound($min) = 1 Then
_ArrayAdd($fl, $o)
EndIf
Next
For $a = 0 To 2
For $b = 0 To 2
For $c = 1 To UBound($fl) - 1
If StringInStr($array[$a + $i][$b + $n], $fl[$c]) Then $array[$a + $i][$b + $n] = $fl[$c]
Next
Next
Next
Next
Next
Local $flag = 0
For $i = 0 To 8
For $n = 0 To 8
If StringLen($array[$i][$n]) > 1 Then $flag = 1
Next
Next
;~ _ArrayDisplay($array)
If $flag = 0 Then ExitLoop
$flag_W += 1
If $flag_W > 10 Then
MsgBox(0,0,"不止一种解,或许条件不完整!")
ExitLoop
endif
WEnd
Return $array
EndFunc ;==>sudoku
|