Sudokulöser (Backtracking)

  • Ich weiß es gab schon viele Sudokulöser, auch mit Backtracking, aber ich soll es gerade in der Schule machen und zum Testen hab ich es jetzt auch in Autoit gemacht. Wegen Backtracking können die Felder auch leer bleiben und er löst es. Wer's braucht, viel Spaß damit:

    (Wenn schon nach beim Eingeben ein Fehler eingegeben wird, spuckt das Programm möglicherweise keine Fehlermeldung und nichts richtiges aus oder braucht ewig)

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #Region ### START Koda GUI section ### Form=
    $Form1 = GUICreate("Sudokulöser", 252, 262, 192, 124)
    dim $Input[9][9],$vars[9][9]
    For $n = 0 To 8 ; Dies hier ist *neu*
    $y = 8 + $n * 20 + Int($n / 3) * 4
    For $i = 0 To 8
    $x = 8 + $i * 24 + Int($i / 3) * 8
    $Input[$i][$n] = GUICtrlCreateInput("", $x, $y, 25, 21)
    Next
    Next ; Ab hier ist wieder alles beim alten
    $Button1 = GUICtrlCreateButton("Lösen", 8, 200, 233, 25)
    $Button2 = GUICtrlCreateButton("Leeren", 8, 230, 233, 25)

    [/autoit] [autoit][/autoit] [autoit]

    For $x=0 To 8
    For $y=0 To 8
    GUICtrlSetLimit($Input[$x][$y],1)
    Next
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Opt("GUIOnEventMode",1)
    GUICtrlSetOnEvent($Button1,"Start")
    GUICtrlSetOnEvent($Button2,"Clean")
    GUISetOnEvent(-3,"_Exit")
    GUISetState(@SW_SHOW)
    #EndRegion ### END Koda GUI section ###

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While Sleep(10)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _Exit()
    Exit
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func Clean()
    For $x=0 To 8
    For $y=0 To 8
    GUICtrlSetData($Input[$x][$y],"")
    Next
    Next
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func Start()
    For $x=0 To 8
    For $y=0 To 8
    $vars[$x][$y]=Int(GUICtrlRead($Input[$x][$y]))
    GUICtrlSetState($Input[$x][$y],$GUI_DISABLE)
    Next
    Next
    If Not backtracking(0,0) Then MsgBox(0,"Fehler","Lösen des Sudokus unmöglich")
    For $x=0 To 8
    For $y=0 To 8
    GUICtrlSetState($Input[$x][$y],$GUI_ENABLE)
    Next
    Next
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func backtracking($x,$y)
    If $vars[$x][$y]=0 Then
    For $i=1 To 9
    If check($x,$y,$i) Then
    GUICtrlSetData($Input[$x][$y],$i)
    $vars[$x][$y]=$i
    If $x=8 And $y=8 Then Return True
    Local $xx=$x,$yy=$y
    If $x=8 Then
    $xx=-1
    $yy+=1
    EndIf
    $xx+=1
    If backtracking($xx,$yy) Then Return True
    $vars[$x][$y]=0
    EndIf
    Next
    Return False
    EndIf
    If $x=8 And $y=8 Then Return True
    Local $xx=$x,$yy=$y
    If $x=8 Then
    $xx=-1
    $yy+=1
    EndIf
    $xx+=1
    If backtracking($xx,$yy) Then Return True
    Return False
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func check($x,$y,$w)
    For $i=0 To 8
    If $vars[$x][$i]=$w Then Return False
    If $vars[$i][$y]=$w Then Return False
    Next
    Local $gfx=Floor($x/3)*3,$gfy=Floor($y/3)*3
    For $i=$gfx To $gfx+2
    For $ii=$gfy To $gfy+2
    If $vars[$i][$ii]=$w Then Return False
    Next
    Next
    Return True
    EndFunc

    [/autoit]

    3 Mal editiert, zuletzt von TheShadowAE (6. Mai 2011 um 20:55)

  • Dieser Sudokulöser gefällt mir :)
    die Testsudokus (leicht) konnte er alle lösen - die auf Stufe schwer
    dauern teilweise etwas ;)
    Ich hab den Teil der GUI etwas gekürzt (bietet sich bei Sudoku ja gradezu an,
    da die Elemente in einer festen Anordnung positioniert sind)

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #Region ### START Koda GUI section ### Form=
    $Form1 = GUICreate("Sudokulöser", 252, 232, 192, 124)
    Dim $Input[9][9], $vars[9][9]
    For $n = 0 To 8 ; Dies hier ist *neu*
    $y = 8 + $n * 20 + Int($n / 3) * 4
    For $i = 0 To 8
    $x = 8 + $i * 24 + Int($i / 3) * 8
    $Input[$i][$n] = GUICtrlCreateInput("", $x, $y, 25, 21)
    Next
    Next ; Ab hier ist wieder alles beim alten
    $Button1 = GUICtrlCreateButton("Lösen", 8, 200, 233, 25)

    [/autoit] [autoit][/autoit] [autoit]

    Opt("GUIOnEventMode", 1)
    GUICtrlSetOnEvent($Button1, "Start")
    GUISetOnEvent(-3, "_Exit")
    GUISetState(@SW_SHOW)
    #EndRegion ### END Koda GUI section ###

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While Sleep(10)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _Exit()
    Exit
    EndFunc ;==>_Exit

    [/autoit] [autoit][/autoit] [autoit]

    Func Start()
    For $x = 0 To 8
    For $y = 0 To 8
    $vars[$x][$y] = Int(GUICtrlRead($Input[$x][$y]))
    GUICtrlSetState($Input[$x][$y], $GUI_DISABLE)
    Next
    Next
    If Not backtracking(0, 0) Then MsgBox(0, "Fehler", "Lösen des Sudokus unmöglich")
    For $x = 0 To 8
    For $y = 0 To 8
    GUICtrlSetState($Input[$x][$y], $GUI_ENABLE)
    Next
    Next
    EndFunc ;==>Start

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func backtracking($x, $y)
    If $vars[$x][$y] = 0 Then
    For $i = 1 To 9
    If check($x, $y, $i) Then
    GUICtrlSetData($Input[$x][$y], $i)
    $vars[$x][$y] = $i
    If $x = 8 And $y = 8 Then Return True
    Local $xx = $x, $yy = $y
    If $x = 8 Then
    $xx = -1
    $yy += 1
    EndIf
    $xx += 1
    If backtracking($xx, $yy) Then Return True
    $vars[$x][$y] = 0
    EndIf
    Next
    Return False
    EndIf
    If $x = 8 And $y = 8 Then Return True
    Local $xx = $x, $yy = $y
    If $x = 8 Then
    $xx = -1
    $yy += 1
    EndIf
    $xx += 1
    If backtracking($xx, $yy) Then Return True
    Return False
    EndFunc ;==>backtracking

    [/autoit] [autoit][/autoit] [autoit]

    Func check($x, $y, $w)
    For $i = 0 To 8
    If $vars[$x][$i] = $w Then Return False
    If $vars[$i][$y] = $w Then Return False
    Next
    Local $gfx = Floor($x / 3) * 3, $gfy = Floor($y / 3) * 3
    For $i = $gfx To $gfx + 2
    For $ii = $gfy To $gfy + 2
    If $vars[$i][$ii] = $w Then Return False
    Next
    Next
    Return True
    EndFunc ;==>check

    [/autoit]

    Wer immer nur das tut, was er bereits kann - wird auch immer nur das bleiben, was er bereits ist!