Autor Beitrag
Tetsuya1
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Di 17.03.09 14:30 
Das Problem was ih 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 hinshreibe da. Weiß leider nicht wo ich den fehler eingebaut habe.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
unit Unit1;

interface

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

type
  Tform1 = class(TForm)
    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..8of 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
  paused.Tag:=9;                   //####
  pausedClick(Sender);             //Deklarationen für die Stopuhr
  vergangene_zeit.Visible:=true;   //####

  //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

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

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

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

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

      5begin
           x:=3;
           y:=3;
           berechnen(x,y,zahl,dlauf);
         end;

      6begin
           x:=6;
           y:=3;
           berechnen(x,y,zahl,dlauf);
         end;

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

      8begin
           x:=3;
           y:=6;
           berechnen(x,y,zahl,dlauf);
         end;

      9begin
           x:=6;
           y:=6;
           berechnen(x,y,zahl,dlauf);
         end;
     end;
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.


Moderiert von user profile iconNarses: Topic aus Algorithmen, Optimierung und Assembler verschoben am Di 17.03.2009 um 14:06


Zuletzt bearbeitet von Tetsuya1 am Di 17.03.09 17:50, insgesamt 1-mal bearbeitet
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 17.03.09 15:07 
Moin!

Und was hast du schon zur Fehlersuche unternommen? Mal ein paar Testausgaben eingebaut, mit dem Debugger durch den Code gegangen, wenigstens die betreffende Stelle mal rausgesucht? Oder sollen wir jetzt die grob 230 Zeilen für dich analysieren? :|

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Tetsuya1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Di 17.03.09 17:56 
Ich habe den Integer Wert Hilfe (Zeile 140) ü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" (Zeile 26) 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 2266
Erhaltene Danke: 4

Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
BeitragVerfasst: Di 17.03.09 18:01 
die Optimierung kannst du beim den Projektoptionen-> compiler ausschalten.
anschließend das Projekt neu erzeugen, nicht bloß compilieren.

crosspost: www.delphipraxis.net...1015353.html#1015353

_________________
Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
Tetsuya1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Di 17.03.09 18:29 
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", "row" untersucht. Die Werte waren schlüssig, weswegen ich mich wunder, warum dieser Fehler zu Stande kommt.
Tetsuya1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Do 19.03.09 21:14 
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
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
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=0do
   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.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
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.