AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Sudoku: Probleme beim Lösen durch systematisches Probieren
Thema durchsuchen
Ansicht
Themen-Optionen

Sudoku: Probleme beim Lösen durch systematisches Probieren

Ein Thema von Salazriel · begonnen am 6. Mär 2010
Antwort Antwort
Salazriel

Registriert seit: 13. Feb 2010
33 Beiträge
 
#1

Sudoku: Probleme beim Lösen durch systematisches Probieren

  Alt 6. Mär 2010, 18:36
Guten Abend.
Bei meinem Sudoku möchte ich, dass das Programm, nachdem es die logischen Algorithmen zu NakedSingles und HiddenSingles angewendet hat, den Rest (existiert etwa ab Schwierigkeitsgrad Schwer verschiedener Anbieter) durch Systematisches Probieren löst.
Dazu ermittelt er erstmal alle leere Zellen und speichert diese in dem globalen dynmischen Array
LeereZellen: Array of Pos (Pos ist ein Record, der zwei Integerwerte x und y hat)
Da die Zahl der leeren Zellen je nach Situation von 0-81 (komplett gelöst-komplett leer) beträgt, nutze ich ein dynamisches Array.
Delphi-Quellcode:
procedure TForm4.LeereZellenBestimmen;
var Spalte,Zeile,i:integer;
begin
i:=-1;
For Spalte:=0 to 8 do
  For Zeile:=0 to 8 do
    If StringGrid1.cells[Spalte,Zeile]=' '
    then
      begin
      inc(i);
      SetLength(LeereZellen,i+1);
      LeereZellen[i].x:=Spalte;
      LeereZellen[i].y:=Zeile;
      end;
end;
Dieses Array soll er dann rekursiv abarbeiten mit der Prozedur RestRaten, der Parameter Zelle ist dabei der Index des Arrays LeereZellen

Delphi-Quellcode:
procedure TForm4.RestRaten(Zelle:integer);
var i,Spalte,Zeile,Zahl:integer;
    Sudoku:string;
    Passt:boolean;
begin
Spalte:=LeereZellen[Zelle].x ;
Zeile:=LeereZellen[Zelle].y; //zur einfacheren Bearbeitung
For Zahl:=1 to 10 do //wenn Zahl=10, dann ist 1..9 kein Element der FeldMenge,
  If Zahl in FeldMenge[Spalte,Zeile]
  then
    begin
    Sudoku:=SudokuInListeSpeichern;
    Sudoku[Zeile*9+Spalte+1]:=inttostr(Zahl)[1];
    SudokuAusListeLaden(Sudoku); //Zahl reinschreiben und FeldMengen neu berechnen
    If Zelle=high(LeereZellen) then exit; //wenn Zelle=high(LeereZellen) sind alle leeren Zellen regelkonform besetzt-->Sudoku gelöst
    RestRaten(Zelle+1); //nächste leere Zelle bearbeiten
    end;
  If Zahl=10
  then
    begin
    Sudoku:=SudokuInListeSpeichern;
    Sudoku[LeereZellen[Zelle-1].x*9+LeereZellen[Zelle-1].y+1]:=' '; //Inhalt der vorherigen leeren Zelle löschen
    SudokuAusListeLaden(Sudoku);
    end;
end;
Der komplette Lösungsalgorithmus nutzt zuerst solange die logischen Prozeduren NakedSingles und HiddenSingles, bis sich nichts mehr ändert. Dann wird LeereZellenBestimmen aufgerufen, dann RestRaten(0).

Das ganze ist eigentlich so gedacht, dass er bei RestRaten folgendes macht:
Füge in die erste leere Zelle die niedrigste regelkonforme Zahl ein und ändere die FeldMengen entsprechend.Dann füge die niedrigste regelkonforme Zahl in die zweite leere Zelle ein und ändere die FeldMengen entsprechend....etc.
Wenn du die Zahlen von 1-9 nicht einsetzen kannst (-->i=10), dann lösche den Inhalt der leeren Zelle vor der bearbeiteten und berechne die FeldMengen entsprechend.
Da 1-9 nicht einsgesetzt werden können, wird auch kein neues RestRaten aufgerufen,weswegen dieser Schritt dann einfach zuende geht. Die Zahl-Variable der leeren Zelle davor zählt also weiter, bis die zweitniedrigste regelkonforme Zahl gefunden wird (da ja mit der erstniedrigsten Zahl die nächste leere Zelle nicht besetzt werden kann), schreibe diese in diese leere Zelle (also die leere Zelle vor der leeren Zelle, die eben nicht besetzt werden konnte) und berechne die FeldMengen neu...etc.

Falls es etwas schwer verständlich war ein Beispiel:
In LeereZelle[6] kann eine 1 geschrieben werden. Also wird die 1 reingeschrieben, die FeldMengen neu berechnet und dann RestRaten(7) aufgerufen. Dieser findet heraus, dass in LeereZelle[7] keine Zahl regelkonform eingesetzt werden kann, weswegen die Zählschleife bei 10 landet. Nun löscht er den Zellinhalt von LeereZelle[6] und beendet RestRaten(7). Die nächsthöhere Rekursionsebene (bin mir nicht sicher, ob dieser Begriff richtig ist) RestRaten(6) wird nun weiter ausgeführt, die Zählschleife zählt Zahl auf 2 hoch und überprüft, ob die 2 regelkonform in LeereZelle[6] eingesetzt werden kann....etc.

Ich bin mir nicht sicher, wo mein Fehler liegt, das Programm weigert sich ganz einfach, dann den Zellinhalt zu löschen und eine Rekursionsebene höher zu gehen.
So füllt er z.B. bei einem leeren Sudoku die 1. Spalte mit 1-9 aus, füllt dann die ersten 3 Felder der 2. Spalte mit 4-6 aus und das 4.-6. Feld mit 1-3.
Für das 7. Feld gibt es nun keine gültige Zahl mehr, 1-6 stehen in derselben Spalte, 7-9 im selben Block. Also müsste er theoretisch die 6. Zelle neu berechnen und höhere Zahlen einsetzen, das nächste wäre die 7. Das macht er aber nicht.

Zur Verdeutlichung habe ich mal die .exe Datei angehängt
(im startenden Hauptmenü auf Sudoku lösen klicken, der Löseknopf macht jetzt nur NakedSingles und HiddenSingles, Button 2 macht LeereZellenBestimmen,Button 3 macht RestRaten(0), so gemacht wegen Testen der Prozeduren)
Angehängte Dateien
Dateityp: exe pgoedicke_426.exe (581,5 KB, 5x aufgerufen)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:08 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz