Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Sudoku Ersteller - 0 wird nicht editiert, sondern bleibt (https://www.delphipraxis.net/131017-sudoku-ersteller-0-wird-nicht-editiert-sondern-bleibt.html)

Tetsuya 17. Mär 2009 15:40


Sudoku Ersteller - 0 wird nicht editiert, sondern bleibt
 
Das Problem was ich habe ist, dass wenn ich das Programm starte, Zufallszahlen erstellt werden, wobei jede Zahl nur einmal in Spalte/Zeile vorkommt, jedoch bleiben die Nullen, welche ich beim erstellen hinschreibe da. Weiß leider nicht wo ich den Fehler eingebaut habe.

Delphi-Quellcode:
unit Unit1;
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, StdCtrls, ExtCtrls;

type
  Tform1 = class(TForm)
    Feld: TStringGrid;
    sudoku_create: TButton;
    loesen: TButton;
    procedure sudoku_createClick(Sender: TObject);
    procedure berechnen(x,y,zahl,dlauf:integer);
    procedure unterquadrat(zahl,dlauf:Integer);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var

  zelle: array[0..8,0..8] of integer;
  Xrow: set of 0..8;       //
  Xcol: set of 0..8;       //Mengenvariable
  zahlen: set of 1..9;
  form1: Tform1;

implementation

{$R *.dfm}


procedure Tform1.sudoku_createClick(Sender: TObject);
var col,row,zahl,dlauf:integer;
begin
  //Zellen leeren - auf Anfangszustand setzen
  for col:=0 to 8 do
    begin
      for row:=0 to 8 do
        begin
          form1.feld.Cells[col,row]:=inttostr(0);
          form1.feld.Color:=clwhite;
        end;
    end;

 //###  Feld [1,1] bis [9,9] füllen ###
  for zahl:=1 to 9 do    // jede Zahlgruppe durcharbeiten (9x die 1; 9x die 2 etc.)
    begin
      for dlauf:=1 to 9 do unterquadrat(zahl,dlauf); // 9x die jeweilige Zahl eintragen
      Xcol:=[];
      Xrow:=[];
    end;
end;


procedure TForm1.unterquadrat(zahl,dlauf:Integer);
var x,y:integer;
begin
  //Unterquadrate 1-9
    case dlauf of

      1: begin
           x:=0;
           y:=0;
           berechnen(x,y,zahl,dlauf);
         end;

     // [...], x,y variiert
end;

procedure TForm1.berechnen(x,y,zahl,dlauf:integer);
var col,row,hilfe:integer;
begin
     // Prüfen ob Zeile oder Spalte schon gesperrt wurde durch eine der Zahlen
     //
     // Hintergrund:
     // Es wird jede Zahl 9x durch die 9 Unterquadrate gerasselt. Dabei muss die jeweilige
     // Spalte/Zeile geblockt werden um die Eindeutigkeit des lösbaren Sudokus zu bewahren.

  col:=random(3)+ x;
  row:=random(3)+ y;

  if col in XCol then berechnen(x,y,zahl,dlauf) //wenn Spalte bereits belegt
    else
      begin
      if row in Xrow then berechnen(x,y,zahl,dlauf) //wenn Zeile bereits belegt
        else
          begin
          hilfe:=strtoint(form1.Feld.Cells[col,row]);
            if hilfe in zahlen then         //prüft ob Feld bereits belegt ist
              begin
               berechnen(x,y,zahl,dlauf); //Zelle ist belegt
              end
            else
              begin
                form1.Feld.Cells[col,row]:=inttostr(zahl);
                zelle[col,row]:=zahl; //Für das abspeichern der Werte
                Xrow:= Xrow + [row]; //Mengenvariable wird erhöht
                Xcol:= Xcol + [col]
              end;
           end;
       end;
  end;
end.
Findet jemand von euch evtl auf Anhieb den kleinen Fehler? Wie gesagt. Es werden einige Felder nicht beachtet, weswegen die 0 dort bleibt.
Bin zwar mit dem Debugger die berechnen Prozedure schon durchgerasselt und habe den Wert Zahl überprüft, aber dennoch finde ich den Fehler nicht. Vielleicht sehe ich den auch nicht, weil ich es selber schrieb...

Frankfurtoder 17. Mär 2009 15:57

Re: Sudoku Ersteller - 0 wird nicht editiert, sondern bleibt
 
Ich werde mir jetzt nicht den Aufwand machen deinen Quelltext durchzusehen. Zwei Fragen ergeben sich für mich.
Warum füllst du das Feld mit 0?
Warum löscht du die 0 nicht einfach selber im nachhinein raus?

Einfach in jedes Feld des Grids schauen und die nullen löschen. zB form1.feld.Cells[col,row]:= '';

Tetsuya 17. Mär 2009 16:03

Re: Sudoku Ersteller - 0 wird nicht editiert, sondern bleibt
 
Das Problem ist nur, wenn das Feld = ' ' ist, hat die Prüfung nicht funktioniert, da es zu einem ungültigen Integerwert in beim Aufruf der Prozedure "berechnen" kommt.

Delphi-Quellcode:
1: begin
  x:=0;
  y:=0;
  berechnen(x,y,zahl,dlauf); //Hier kommt der Fehler
end;
Deswegen habe ich die 0 verwendet. Jene wird auch so überschrieben.

Ich habe auch den Integer Wert Hilfe überwacht, bzw. versuchte es. "Auf Variable 'hilfe' kann wegen Optimierung nicht zugegriffen werden"
Es läuft ja so, dass nacheinander die Zahlen von 1-9 je 9x eingefügt werden. Wenn eine Zahl in dem Feld bereits Teil der Menge "zahlen: set of 1..9" ist, heißt es ja, dass die Zeile/Spalte belegt ist. Habe Danach mal Testweise aus 1..9 eine 0..9 gemacht, was ja heißen würde, dass sich das Programm aufhängt, da vorerst überall eine 0 ist.

Jedoch wird weiterhin die gleiche Lösung angeboten mit allen Zahlen, bei denen die Zeilen/Spalten von der Struktur (eines Sudoku) funktionieren und etwa 20x der 0, welche ich am Anfang rein geschrieben habe, da das leere Wort schlecht eine Zahl darstellen kann.
Weiß leider nicht, wieso er dennoch den Algorithmus ausführt, da dies nicht sein dürfte.

Keldorn 17. Mär 2009 16:05

Re: Sudoku Ersteller - 0 wird nicht editiert, sondern bleibt
 
alos ich finde es schon ein wenig frech, wenn du im DF http://www.delphi-forum.de/viewtopic.php?t=90939 die gleiche Frage stellst, dot schon Antworten hast und hier später (!) die Frage erneut stellst.

Wenn, dann solltest du wenigstens den crosspost deutlich machen, damit nicht doppelt geantwortet wird und sich mehrere umsonst mit DEINEM Problem auseinandersetzen

Tetsuya 17. Mär 2009 16:08

Re: Sudoku Ersteller - 0 wird nicht editiert, sondern bleibt
 
Naja. Es ist ja so, dass nicht jeder User auf beiden Foren unterwegs ist und jeder hat eine andere Denkstruktur.
Glaube nicht, dass es falsch ist an mehreren Stellen zu fragen. Ansonsten tut es mir leid.

Keldorn 17. Mär 2009 16:11

Re: Sudoku Ersteller - 0 wird nicht editiert, sondern bleibt
 
Zitat:

Zitat von Tetsuya
Glaube nicht, dass es falsch ist an mehreren Stellen zu fragen.

is es in meinen Augen auch nicht, wenn Du das kenntlich machst (Link einfügen). Es gibt sicher viele Leute, die sich alle Threads durchlesen und auch zu etwas älteren Problemen Lösungen posten. ist dann vergebene Mühe, wenn dann im anderen Forum schon ne Lösung steht, meinst Du nicht?

Tetsuya 17. Mär 2009 16:15

Re: Sudoku Ersteller - 0 wird nicht editiert, sondern bleibt
 
Werde ich beim nächsten Beitrag berücksichtigen mit den Crosspost Link.

Ich habe jetzt nur das erste Unterquadrat unter die Lupe genommen und es ist so, dass zwischen 2-4x der 0 immer drinnen ist. Wird demnach nicht gelöscht.
Dabei variieren die eingegebenen Zahlen weiterhin (heißt, dass manchmal 1-5 drinnen ist oder [1..3,5,6,9].
Der Fehler muss demnach an der Prozedure "berechnen" legen oder sogar beim "Sudoku Create", da bei jenem die Zahlen, welche eingesetzt werden sollen, bestimmt werden.
Habe "Hilfe", "col" und "row" untersucht. Die Werte waren schlüssig, weswegen ich mich wunder, warum dieser Fehler zu Stande kommt.

Tetsuya 19. Mär 2009 19:15

Re: Sudoku Ersteller - 0 wird nicht editiert, sondern bleibt
 
//Gleiche Beitrag bei dem anderem Crosspost

Sry für Doppelpost. Topic soll nur wieder als aktuell gekennzeichnet werden.

Also der Fehler muss in der Schleife liegen. Habe eine 2. Variante mir ausgedacht, welche jedoch auch nicht funktioniert.
Die Zahl bis 3 geht wunderbar. Sobald er aber die 4 durchrasseln soll ist Schluss.

Es kommt dann zu einem Stack Overflow bzw. Aufhängen des Programmes

Iterartiv - Programm bleibt hängen
Delphi-Quellcode:
procedure TForm1.berechnen(x,y,zahl:integer);
  var col,row,hilfe:integer;
  begin

  col:=random(3)+ x; //x gibt den Wert des Unterbereiches an
  row:=random(3)+ y;
  hilfe:=strtoint(form1.Feld.Cells[col,row]); //liest den Wert der Zelle aus (es werden alle Zellen vorher mit 0 beschrieben

  while not (hilfe=0) do
   begin
     while col in XCol do //Xcol beinhaltet die Werte der geblockten Spalten
       begin
        col:=random(3+x);
         while row in Xrow do
          begin
            row:=random(3)+ y
          end;
       end;
     hilfe:=strtoint(form1.Feld.Cells[col,row]);
     end;

  form1.Feld.Cells[col,row]:=inttostr(zahl); //Schreiben der Zahl in die Zelle
  Xrow:= Xrow + [row]; //Zeile wird geblockt
  Xcol:= Xcol + [col]

Und bei dem hier kommt es zum Stack Überlauf. Dies liegt daran, dass ich die Procedure selber immer wieder aufrufe und dadurch der Speicher zu extrem ausgelastet wird.
Weiß leider nicht wie ich die Procedure umschreiben könnte.

Delphi-Quellcode:
procedure TForm1.berechnen(x,y,zahl:integer);
var col,row,hilfe:integer;
begin
  col:=random(3)+ x;
  row:=random(3)+ y;
  if then berechnen(x,y,zahl,dlauf) //wenn Spalte bereits belegt
    else
      begin
      if then berechnen(x,y,zahl,dlauf) //wenn Zeile bereits belegt
        else
          begin

            if hilfe in zahlen then         //prüft ob Zelle bereits belegt ist
              begin                        
               berechnen(x,y,zahl,dlauf); //ruft sich selber nochmal auf
              end
            else
              begin
                form1.Feld.Cells[col,row]:=inttostr(zahl); //Schreiben der Zahl
                zelle[col,row]:=zahl; //Für das abspeichern der Werte
                Xrow:= Xrow + [row]; //Mengenvariable wird erhöht
                Xcol:= Xcol + [col]
              end;
           end;
       end;
  end;
Der generell Quelltext ist oben zu sehen. Aber in dieser Procedure liegt der Fehler. Bei 1-3 geht es wunderbar. Bei der Zahl 4 bricht er jedoch beim achten Unterquadrat ab, obwohl die case of vorgegeben ist und er nur reinspringen muss.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:01 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