Hey,
Ich habe grade einen Sudoku Löser geschrieben, der meiner Meinung nach ziemlich schnell für AutoIt ist.
Sagt mir bitte wie ihn ihn findet. Um das Programm zu benutzen schreibt man die Sudokus in ein Text Dokument und wählt sie im Programm aus.
Ich habe ein paar sudokus zum testen beigelegt.
Spoiler anzeigen
;Coded by FireAlex
[/autoit] [autoit][/autoit] [autoit]Opt("MustDeclareVars",1)
Global $aSudoku[9][9],$aSolved[9][9],$aPencilmarks[9][9][9],$iSolvedValues,$sSaves=""
Main()
Func Main()
Local $sTimer
;~ Local $sFilePath="SuperHard.txt"
Local $sFilePath=FileOpenDialog("Choose Sudoku File",@ScriptDir,"Sudokus (*.txt)")
$aSudoku=ReadSudoku($sFilePath)
ConsoleWrite("Solving sudoku:"&@LF&@LF)
PrintSudoku($aSudoku)
$sTimer=TimerInit()
$aSudoku=SolveSudoku($aSudoku)
ConsoleWrite(@LF&"Solved in "&TimerDiff($sTimer)&" ms"&@LF&@LF)
PrintSudoku($aSudoku)
SaveSudoku(StringReplace($sFilePath,".txt","_solved.txt"),$aSudoku)
EndFunc
Func SolveSudoku($aSudoku)
Local $iSolvedValuesOld
$iSolvedValues=0
For $i=0 To 8
For $j=0 To 8
$aSolved[$i][$j]=0
For $k=0 To 8
$aPencilmarks[$i][$j][$k]=1
Next
Next
Next
For $i=0 To 8
For $j=0 To 8
$k=$aSudoku[$i][$j]
If $k<>"" Then
NewValueFound($i,$j,$k)
EndIf
Next
Next
While 1
$iSolvedValuesOld=$iSolvedValues
Method1()
Method2()
Method3()
Method4()
If CheckBroken() Then
Undo()
ContinueLoop
EndIf
If $iSolvedValuesOld=$iSolvedValues Then
Guess()
ContinueLoop
EndIf
If $iSolvedValues=81 Then Return $aSolved
WEnd
EndFunc
Func Method1()
Local $iSum,$iSingleCandidate
;http://www.sudokuoftheday.com/pages/techniques-2.php
For $i=0 To 8
For $j=0 To 8
If $aSolved[$i][$j]=0 Then
$iSum=0
$iSingleCandidate=0
For $k=0 To 8
If $aPencilmarks[$i][$j][$k] Then
$iSum+=1
$iSingleCandidate=$k
EndIf
Next
If $iSum=1 Then
;~ ConsoleWrite("Method 1: "&$i&" - "&$j&" - "&($iSingleCandidate+1)&@LF)
NewValueFound($i,$j,$iSingleCandidate+1)
EndIf
EndIf
Next
Next
EndFunc
Func Method2()
Local $iSum,$iSingleCell
;http://www.sudokuoftheday.com/pages/techniques-1.php
;Rows
For $i=0 To 8;Row
For $j=0 To 8;Number to Check
$iSum=0
$iSingleCell=0
For $k=0 To 8
If $aPencilmarks[$i][$k][$j] Then
$iSum+=1
$iSingleCell=$k
EndIf
Next
If $iSum=1 And $aSolved[$i][$iSingleCell]=0 Then
;~ ConsoleWrite("Method 2: "&$i&" - "&$iSingleCell&" - "&($j+1)&@LF)
NewValueFound($i,$iSingleCell,$j+1)
EndIf
Next
Next
EndFunc
Func Method3()
Local $iSum,$iSingleCell
;http://www.sudokuoftheday.com/pages/techniques-1.php
;Coloumns
For $i=0 To 8;Coloumn
For $j=0 To 8;Number to Check
$iSum=0
$iSingleCell=0
For $k=0 To 8
If $aPencilmarks[$k][$i][$j] Then
$iSum+=1
$iSingleCell=$k
EndIf
Next
If $iSum=1 And $aSolved[$iSingleCell][$i]=0 Then
;~ ConsoleWrite("Method 3: "&$iSingleCell&" - "&$i&" - "&($j+1)&@LF)
NewValueFound($iSingleCell,$i,$j+1)
EndIf
Next
Next
EndFunc
Func Method4()
Local $iSum,$iSingleCellRow,$iSingleCellColoumn
;http://www.sudokuoftheday.com/pages/techniques-1.php
;Squares
For $i=0 To 2;Square Row
For $j=0 To 2;Square Coloumn
For $k=0 To 8;Number to Check
$iSum=0
$iSingleCellRow=0
$iSingleCellColoumn=0
For $l=0 To 2;Cell Row
For $m=0 To 2;Cell Coloumn
If $aPencilmarks[$i*3+$l][$j*3+$m][$k] Then
$iSum+=1
$iSingleCellRow=$i*3+$l
$iSingleCellColoumn=$j*3+$m
EndIf
Next
Next
If $iSum=1 And $aSolved[$iSingleCellRow][$iSingleCellColoumn]=0 Then
;~ ConsoleWrite("Method 4: "&$iSingleCellRow&" - "&$iSingleCellColoumn&" - "&($k+1)&@LF)
NewValueFound($iSingleCellRow,$iSingleCellColoumn,$k+1)
EndIf
Next
Next
Next
EndFunc
Func NewValueFound($row,$col,$value)
;~ ConsoleWrite("NewValueFound: "&$row&"/"&$col&" = "&$value&@LF)
$iSolvedValues+=1
$aSolved[$row][$col]=$value
$value-=1
For $i=0 To 8
If $i=$value Then
$aPencilmarks[$row][$col][$i]=1
Else
$aPencilmarks[$row][$col][$i]=0
EndIf
If $i<>$col Then $aPencilmarks[$row][$i][$value]=0
If $i<>$row Then $aPencilmarks[$i][$col][$value]=0
Next
For $i=0 To 2
For $j=0 To 2
If Floor($row/3)*3+$i<>$row Or Floor($col/3)*3+$j<>$col Then $aPencilmarks[Floor($row/3)*3+$i][Floor($col/3)*3+$j][$value]=0
Next
Next
EndFunc
[/autoit] [autoit][/autoit] [autoit]Func Guess()
;~ ConsoleWrite("Guessing..."&@LF)
$sSaves=PencilmarksToString($aPencilmarks)&","&$sSaves
For $i=0 To 8
For $j=0 To 8
If $aSolved[$i][$j]=0 Then
For $k=8 To 0 Step -1
If $aPencilmarks[$i][$j][$k]=1 Then
NewValueFound($i,$j,$k+1)
Return
EndIf
Next
EndIf
Next
Next
EndFunc
Func Undo()
Local $iPos
;~ Do
;~ ConsoleWrite("Whoops wrong guess!..."&@LF)
$iPos=StringInStr($sSaves,",")
$aPencilmarks=PencilmarksFromString(StringLeft($sSaves,$iPos-1))
$sSaves=StringMid($sSaves,$iPos+1)
$iSolvedValues=0
For $i=0 To 8
For $j=0 To 8
$aSolved[$i][$j]=0
Next
Next
Method1()
For $i=0 To 8
For $j=0 To 8
If $aSolved[$i][$j]=0 Then
For $k=8 To 0 Step -1
If $aPencilmarks[$i][$j][$k]=1 Then
$aPencilmarks[$i][$j][$k]=0
Return
EndIf
Next
EndIf
Next
Next
;~ Until Not CheckBroken()
EndFunc
Func CheckBroken()
Local $iSum
For $i=0 To 8
For $j=0 To 8
$iSum=0
For $k=0 To 8
$iSum+=$aPencilmarks[$i][$j][$k]
Next
If $iSum=0 Then Return True
Next
Next
Return False
EndFunc
Func PencilmarksToString($aPencilmarks)
Local $sString=""
For $i=0 To 8
For $j=0 To 8
For $k=0 To 8
If $aPencilmarks[$i][$j][$k] Then $sString&=$k
Next
$sString&="|"
Next
Next
Return $sString
EndFunc
Func PencilmarksFromString($sString)
Local $aPencilmarks[9][9][9]
Local $iPos
For $i=0 To 8
For $j=0 To 8
For $k=0 To 8
$aPencilmarks[$i][$j][$k]=0
Next
$iPos=StringInStr($sString,"|")
For $k=1 To $iPos-1
$aPencilmarks[$i][$j][0+StringMid($sString,$k,1)]=1
Next
$sString=StringMid($sString,$iPos+1)
Next
Next
Return $aPencilmarks
EndFunc
Func _DebugPencilmarks($aPencilmarks)
For $i=0 To 8
ConsoleWrite("|")
For $j=0 To 8
For $k=0 To 8
If $aPencilmarks[$i][$j][$k]=1 Then
ConsoleWrite($k+1)
Else
ConsoleWrite(" ")
EndIf
Next
ConsoleWrite("|")
Next
ConsoleWrite(@LF)
Next
ConsoleWrite(@LF)
ConsoleWrite(@LF)
EndFunc
Func PrintSudoku($aSudoku)
For $i=0 To 8
If Mod($i,3)=0 Then ConsoleWrite("-------------"&@LF)
For $j =0 To 8
If Mod($j,3)=0 Then ConsoleWrite("|")
If $aSudoku[$i][$j] = 0 Then
ConsoleWrite(" ")
ContinueLoop
EndIf
ConsoleWrite($aSudoku[$i][$j])
Next
ConsoleWrite("|"&@LF)
Next
ConsoleWrite("-------------"&@LF&@LF)
EndFunc
Func ReadSudoku($sFilePath)
Local $aSudoku[9][9],$hFile,$sLine
$hFile=FileOpen($sFilePath,0)
For $i=0 To 8
$sLine=FileReadLine($hFile)
For $j=0 To 8
$aSudoku[$i][$j]=Int(StringMid($sLine,$j+1,1))
Next
Next
Return $aSudoku
EndFunc
Func SaveSudoku($sFilePath,$aSudoku)
Local $hFile=FileOpen($sFilePath,2)
For $i=0 To 8
For $j=0 To 8
FileWrite($hFile,$aSudoku[$i][$j])
Next
FileWrite($hFile,@CRLF)
Next
EndFunc