Das Problem Sie ist mit sind, dass einige Ihrer rekursive Anrufe werden Ihre Lösung nicht richtig, die Ergebnisse zurückkehrt, so, wenn es gefunden wird, wird über ein paar vergessen erhöht den rekursiven Stack. Hier ist das erste Update, das Sie benötigen, das Hinzufügen return
die rekursiven Anrufe in mover
:
def mover(self, row, col):
if col + 1 != 9:
return self.solve_helper(row, (col+1)) # added return
elif row + 1 != 9:
print "Moving to row" + str(row + 1)
return self.solve_helper((row+1),0) # here too
else:
print "SOLUTION FOUND"
return True
Sie müssen auch etwas ähnliches in dem speziellen Fall Ihrer solve_helper
Funktion, wo man über bereits gelösten Zellen überspringt. Das Ende der Funktion sollte sein:
else:
return self.mover(row, col) # added return
return False
Edit:
Ok, ich habe noch ein paar Probleme im Code gefunden. Zwei von ihnen sind logische Probleme mit dem Solver, und einer ist ein Anzeigeproblem, das keine wirklichen Probleme verursacht, außer seltsam beim Lösen zu sein.
Die Themen:
- Zuerst sind Sie neuesten Code
solve_helper
Aufruf selbst hat, anstatt mover
Aufruf. Das erfordert einen zusätzlichen Funktionsaufruf vor dem Verschieben (obwohl ich denke, dass es den Solver nicht wirklich unterbricht).
- Zweitens, wenn
solve_helper
setzt eine Zelle auf 9, aber dann in Backtracked zu (nach einigen späteren Zellen konnte nicht gelöst werden), wird die 9 nicht auf Null zurückgesetzt, bevor Backtracking weiter.
- Und zuletzt, das Display Problem. Wenn Sie Zellen auf 0 setzen, wird der alte Wert nicht angezeigt. Dies sah sehr ähnlich aus wie das Problem in # 2 (mit 9s nach dem Zurückverfolgen zurückgelassen), aber in Wirklichkeit ist es nur kosmetisch.
Das erste Problem ist einfach zu beheben. Ändern Sie einfach den Anruf zu einem mover
Anruf stattdessen. Genau das hatten Sie in dem ursprünglichen Code, den Sie in die Frage eingefügt haben. Der Aufruf von solve_helper
führt direkt nicht zu einem falschen Ergebnis (da solve_helper
die bereits ausgefüllte Zelle das zweite Mal überspringt), aber es fügt jeder Ebene Ihrer Rekursion einen unnötigen zusätzlichen Funktionsaufruf hinzu.
Das zweite Problem ist ein wenig komplizierter, und hier stecken Sie auf einigen Boards fest. Was Sie tun müssen, ist die Linie, die self.set_cell(row, col, 0)
aus dem else
Block ist es derzeit in Bewegung ist. In der Tat können Sie es tatsächlich außerhalb der Schleife vollständig verschieben, wenn Sie wollen (da es nur wirklich notwendig ist, wenn Sie sind Backtracking, nachdem keiner der Werte für die aktuelle Zelle funktioniert hat).Hier ist, was ich denke, das ist die beste Anordnung der for-Schleife (auch die return False
Anweisung oben bewegt):
for i in range(1,10):
print("Setting value ") + str (i) + (" at ") + str(row) + ", " + str(col)
self.set_cell(row, col, i)
self.guesses = self.guesses + 1
if self.check_cell(row, col):
if self.mover(row, col):
return True
print "Backtracking"
self.set_cell(row, col, 0)
return False
Schließlich Fixierung das Anzeigeproblems erfordert zwei Änderungen. Zuerst werden Sie die Bedingung in set_cell
loswerden. Sie möchten die Anzeige immer aktualisieren. Als nächstes, in update_textfield
, verschieben Sie die delete
Anruf außerhalb der if
Block, so dass es immer passiert (lassen Sie die insert
unter der if
). Dies macht es so, dass das Setzen einer Zelle auf Null den vorherigen Wert löscht, aber nicht, dass sie ein tatsächliches 0-Zeichen anzeigt (es wird nichts angezeigt).
Ich denke, das sollte es tun. Beachten Sie, dass der von Ihnen verwendete Algorithmus immer noch ziemlich langsam ist. Lösen a board I found on the internet in a quick Google search dauerte 122482 Vermutungen und mehr als 5 Minuten, aber es hat endlich funktioniert. Andere Boards (vor allem solche, die in den ersten paar Freiräumen 8er oder 9er benötigen) können noch länger dauern.
Überspringt die Funktion, wie sie bereits ist, nicht-Null-Werte, durch die else-Anweisung als Teil des solve_helper? –
@CluelessCoder: Das Problem besteht darin, dass Sie nach dem Überspringen eines Werts ungleich Null, indem Sie zum Block "else" wechseln, immer False zurückgeben, auch wenn die Lösung gefunden wurde. Jedes Mal, wenn Sie rekrutieren, müssen Sie bereit sein, "True" zurückzugeben, wenn dieser Aufruf zur Lösung führt. Sie möchten nur False zurückgeben, wenn Sie den aktuellen Board-Status aufgegeben haben und zurückgehen müssen. – Blckknght
Ich bin mir immer noch nicht sicher, wie False übergeben wird, und ich bin mir nicht sicher, wie ich die Nicht-Nullen richtig leite. Der Code scheint rückgängig zu sein, übergibt jedoch den richtigen Wert und führt dazu, dass die leeren Zeichen in drei Zeilen alle in Neuner-Zahlen umgewandelt werden. –