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



BeitragVerfasst: Sa 14.03.09 19:45 
Ich bastle gerade ein Sudoku für unseren Info Unterricht.

Ich habe mir überlegt, dass die Prozedur zum erstellen des Sudoku folgendermaßen aufgebaut ist:
Er beginnt mit 1, rasselt diese 9 mal durch, sodass in jedem Unterquadrat eine 1 steht. Sobald eine 1 positioniert wurde, habe ich vor, die Spalte/Zeile zu sperren, sodass es bereits eindeutig wird. Danach werden die Spalten/Zeilen wieder freigestellt und der rattert die 2 9x durch. Bei bereits belegtem Feld wird ein anderes Feld gesucht.

Soviel zur Idee. Umsetzung sieht wieder ganz anders aus.
Ich habe ein Array

ausblenden Delphi-Quelltext
1:
var  tZelle : array[0..80..8of Integer;					


In jenem habe ich vor, die Spalte/Zeile zu sperren, indem ich einfach die Zahl rauslösche. Wär dies überhaupt möglich, da ich das Array direkt vorgegeben habe?
Ist es ebenfalls möglich. Angenommen es würde funktionieren mit dem rausstreichen, dass man ein Random Befehl so schreibt, dass er eine ZUufallszahl aus den restlichen Spalten/Zeilen zieht oder muss dies dann über eine case of bzw if-Schleife erledigt werden?
freak4fun
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 604
Erhaltene Danke: 4

Win 7 Pro
VS 2013 Express, Delphi, C#, PHP, Java
BeitragVerfasst: Sa 14.03.09 19:58 
Es wäre von Vorteil ein Array mit eigenem Datentyp zu basteln. Sei es mit einer Klasse oder einem Record.
Ein Feld könnte dann mehrere Daten enthalten, wie zB Zahl, Editierbar, ... ODer auch das Komplette Feld als Klasse.
Denk mal drüber nach. ;)

_________________
"Ich werde auf GAR KEINEN Fall…!" - "Keks?" - "Okay, ich tu's."
i++; // zaehler i um 1 erhoehen
Tetsuya1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Sa 14.03.09 20:14 
Ich erstelle das Sudoku innerhalb eine Stringgrids und bei jeder Zahl, die übrig bleiben soll, entfern ich einfach die Editierungsmöglichkeit.
freak4fun
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 604
Erhaltene Danke: 4

Win 7 Pro
VS 2013 Express, Delphi, C#, PHP, Java
BeitragVerfasst: So 15.03.09 14:19 
user profile iconTetsuya1 hat folgendes geschrieben Zum zitierten Posting springen:
Ich erstelle das Sudoku innerhalb eine Stringgrids und bei jeder Zahl, die übrig bleiben soll, entfern ich einfach die Editierungsmöglichkeit.

Da würde ich von abraten. Du benutzt eine VCL-Komponente als Arbeitskomponente und nicht nur zur Darstellung. Das ist sagen wir, unschön. ;)

Such mal hier im Forum wie du Sodukos erstellst. Da gib es einiges. ;) Dann schreibst du eine Methode, die das macht und anschließend das StringGrid füllt (zB per OUT-Parameter). Ich hoffe das hilft dir weiter. :)

_________________
"Ich werde auf GAR KEINEN Fall…!" - "Keks?" - "Okay, ich tu's."
i++; // zaehler i um 1 erhoehen
Tetsuya1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: So 15.03.09 20:33 
Hab gerade einen Exception Fehler. Weiß aber nicht wieso...
Als Grund wird gesagt, dass es kein möglicher Integerwert ist. Habe die Stelle, welcher er mir anzeigt mit <<<<<<<<<<<<<<<<<<<<< vorher und nachher markiert
Weiß dazu evtl. einer Rat?

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:
procedure Tform1.sudoku_createClick(Sender: TObject);
var  col,row,zahl,dlauf:integer;
begin
  Leer(col,row);  //Zellen leeren auf '' - Anfangszustand

 //###  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
        begin
          unterquadrat(zahl,dlauf);  // 9x die jeweilige Zahl eintragen
        end;

    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;

 //geht weiter bis 9
end;


procedure TForm1.berechnen(x,y,zahl,dlauf:integer);
var col,row,hilfe:longint;
begin
col:=10;  //Dass die Prüfung absolviert wird, ob die Spalte/Zeile noch frei ist. Daher ein Wert der nie vorkommt
row:=10;  //leider unsaubere Programmierung, welche ich später entfernen werde

     // Prüfen ob Zeile/Spalte schon belegt 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.

  while not col in Xcol do col:=random(3)+ x;
  while not row in Xrow do row:=random(3)+ y;
  hilfe:=strtoint(form1.Feld.Cells[col,row]);
   if hilfe in zahlen then
     begin
        unterquadrat(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];  //Verringerung der Möglichkeiten
       Xcol:= Xcol - [col];
    end;
   end;


Habe den Code etwas gekürzt. Jedoch haben die rausgelöschten Sachen nichts mit dem Problem zu tun
freak4fun
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 604
Erhaltene Danke: 4

Win 7 Pro
VS 2013 Express, Delphi, C#, PHP, Java
BeitragVerfasst: So 15.03.09 21:40 
Versuche mal selbst zu debuggen. BreakPoint auf die Berechnen-Prozedur und dann mal mit F7 in die Methode bzw. mit F8 dann weiter durch gehen. ;) Dann dazu noch die Werte überwachen. SChau mal ob du so den fehler findest. :)

Edit:
ausblenden Delphi-Quelltext
1:
hilfe:=strtoint(form1.Feld.Cells[col,row]);					

Wenn das Feld keine Zahl enthält, sprich leer ist, gibt es auch einen Fehler.

_________________
"Ich werde auf GAR KEINEN Fall…!" - "Keks?" - "Okay, ich tu's."
i++; // zaehler i um 1 erhoehen
Tetsuya1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: So 15.03.09 21:53 
Habe es verändert, dass davor jedes Feld mit einer 0 versehen wird. Dennoch gleiche Fehler...
freak4fun
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 604
Erhaltene Danke: 4

Win 7 Pro
VS 2013 Express, Delphi, C#, PHP, Java
BeitragVerfasst: So 15.03.09 23:48 
user profile iconTetsuya1 hat folgendes geschrieben Zum zitierten Posting springen:
Habe es verändert, dass davor jedes Feld mit einer 0 versehen wird. Dennoch gleiche Fehler...

Hast du fixedCols/Rows bzw. Felder im Stringgrid die andere Werte haben? Wenn x = 0 und col:=random(3) auch 0, dann greifst du eventuel auf Felder zu, die anders als mit Zahlen beschriftet sind. :nixweiss:

_________________
"Ich werde auf GAR KEINEN Fall…!" - "Keks?" - "Okay, ich tu's."
i++; // zaehler i um 1 erhoehen
Tetsuya1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Mo 16.03.09 18:13 
Habe nun 2 Stunden versucht das Problem zu lösen indem ich unter anderem versuchte die Prozedure einfach wegzulassen oder globale Variablen zu erstellen. Alles kein Erfolg. Cols/Rows gehen von 0 bis 8. Also ein 9x9 Feld wie eben ein normales Sudoku aussieht. Fixiert wurden keine Werte. Dies mach ich später mit Zugriffsverweigerung.
Weiß nicht mehr was ich für einen Fehler ich da rein geschrieben habe. Deswegen stelle ich den ganzen Quelltext mal hier rein. Auch wenn es viel Verlangt ist, würde sich einer den mal anschauen und evtl. sogar den Fehler finden?

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:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
unit Unit1;

interface

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

type
  Tform1 = class(TForm)
    exit: TButton;
    Feld: TStringGrid;
    SGrad: TGroupBox;
    dif_easy: TRadioButton;
    dif_hard: TRadioButton;
    dif_middle: TRadioButton;
    save: TButton;
    load: TButton;
    print: TButton;
    OpenDialog1: TOpenDialog;
    SaveDialog1: TSaveDialog;
    PrintDialog1: TPrintDialog;
    Timer: TTimer;
    uhr: TLabel;
    paused: TButton;
    vergangene_Zeit: TGroupBox;
    Help: TButton;
    sudoku_create: TButton;
    loesen: TButton;
    GroupBox1: TGroupBox;
    procedure exitClick(Sender: TObject);
    procedure sudoku_createClick(Sender: TObject);
    procedure FeldDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
    procedure FeldKeyPress(Sender: TObject; var Key: Char);
    procedure berechnen(x,y,zahl,dlauf:integer);
    procedure unterquadrat(zahl,dlauf:Integer);
    procedure pausedClick(Sender: TObject);
    procedure TimerTimer(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  StartZeit: TDateTime;     //####
  StopZeit:  TDateTime;     //Für die Stopuhr Deklaration
  Zeitsumme: TDateTime;     //####

  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.exitClick(Sender: TObject);
begin
  close
end;

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:=Xcol + [1..9];
      Xrow:=Xrow + [1..9];
    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);  // hier kommt die Meldung "ist kein gültiger Integerwert".
         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
  col:=10//Dass die Prüfung absolviert wird, ob die Spalte/Zeile noch frei ist. Daher ein Wert der nie vorkommt
  row:=10;  //leider unsaubere Programmierung, welche ich später entfernen werde

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

  while not col in Xcol do col:=random(3)+ x;
  while not row in Xrow do row:=random(3)+ y;
  hilfe:=strtoint(form1.Feld.Cells[col,row]);

   if hilfe in zahlen then
     begin
        unterquadrat(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];
       Xcol:= Xcol - [col];
    end;
   end;


procedure Tform1.FeldDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
var s:string;
begin

//Zellen einheitlich machen (dicke Ränder + zentrierte Textausgabe)
 with sender as TStringGrid do
    begin
      canvas.Brush.Color:= clwhite;
      canvas.font.color:= clblack;
      feld.canvas.FillRect(rect);    //Hintergrund der Zelle füllen

      s:=cells[acol,arow];   //Zelltext holen...
      DrawText(canvas.Handle,PChar(s), StrLen(PChar(s)),Rect,DT_CENTER or DT_VCENTER or DT_SINGLELINE); //...und zentral ausgeben

// Einteilung malen
      canvas.Pen.Color:= clblack;
      Canvas.Pen.Width:=3;

    //aller 3 Zellen die Linien stärker malen und nur im Bereich der zu zeichnenen Zelle zeichnen
      if ((acol+1mod 3)=0 then
        begin
         //Strich rechts
          canvas.moveto(Rect.Right,rect.top);
          canvas.LineTo(Rect.Right,rect.bottom);
        end;
      if ((arow+1mod 3)=0 then
        begin
         //Strich unten
          canvas.moveto(Rect.left,rect.Bottom);
          canvas.LineTo(Rect.Right,rect.bottom);
        end;
    end;
end;


procedure Tform1.FeldKeyPress(Sender: TObject; var Key: Char);
begin
  with sender as TStringGrid do
    begin
      //Änderungen nur, wenn Zelle leer ist und eine Zahlentaste gedrückt wurde
      if (cells[col,row]=''and (key in ['1'..'9']) then
        cells[col,row]:=key;
    end;
end;

procedure Tform1.pausedClick(Sender: TObject);
begin
  case paused.Tag of //Merkt sich dern Wert der eingegebenen Klicks auf den Button

    0begin//Uhr wird gestartet
         StartZeit:=now-ZeitSumme;
         Timer.Enabled:=true;
         paused.Caption:='Pause';
       end;

    1begin //Uhr wird angehalten
         StopZeit:=now;
         Timer.Enabled:=false;
         paused.Caption:='Weiter';
         ZeitSumme:=StopZeit-StartZeit;   //berrechnen der abgelaufenen Zeit
         Uhr.Caption:=TimeToStr(ZeitSumme);
       end;

/// Neustart des Spieles - Ausgangszeit
    9begin //Uhr auf 00:00:00
         StartZeit:=now;
         Timer.Enabled:=true;
         paused.Caption:='Pause';
         paused.Tag:=0;
       end;
  end;

  //Klicks des Buttons zurücksetzen
  paused.Tag:=paused.Tag + 1;
  if paused.Tag > 1 then paused.Tag := 0;
end;

procedure Tform1.TimerTimer(Sender: TObject);
begin
  //abgelaufene Zeit berechnen und im Label Uhr anzeigen
  Uhr.Caption:= TimeToStr(now - StartZeit);
end;

end.


Ich hoffe, dass einer den Fehler findet. Habe ihn nochmal hervorgehoben
GTA-Place
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Mo 16.03.09 18:29 
Der Fehler ist ganz einfach: Bei dir fehlen Klammern.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
var
  XCol: Set of 0..8;
  Col:  Integer;
begin
  Col := 10;                    // Col = 10

  while not Col in XCol do       // Solange (not Col)* in XCol ist...
    Col := Random(3) + 5;       // wird nicht aufgerufen, (not Col)* ist ja auch nicht in XCol

  Showmessage(IntToStr(Col));   // Col = 10
end;


*(not Col) = -11; Richtig:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
var
  XCol: Set of 0..8;
  Col:  Integer;
begin
  Col := 10;                    // Col = 10

  while not (Col in XCol) do     // Solange not (Col in XCol) ist...
    Col := Random(3) + 5;       // wird aufgerufen, da 10 nicht in XCol ist

  Showmessage(IntToStr(Col));   // Col z.B. = 6
end;

_________________
"Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
Tetsuya1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 21



BeitragVerfasst: Mo 16.03.09 18:56 
Habe es nun verändert. Danke für den Hinweis. Wusste nicht, dass der dann ein Vorzeichenwechsel macht, jedoch ist es nun so, wenn ich das Programm starte, dass zwar kein Fehler mehr erscheint, jedoch hängt sich das Programm auf beim Starten des Projektes, was natürlich nicht sein dürfte.