Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Zugriffsverletzung (https://www.delphipraxis.net/72437-zugriffsverletzung.html)

Chii 30. Jun 2006 09:10


Zugriffsverletzung
 
Hallo!

Ich wollte ein Sudoku-Rätsel-Programm schreiben, wo der PC selber per random ein Sudoku erstellt. Hierzu habe ich erstmal die erste Zeile generiert und wollte diese dann ausgeben lassen.

Dabei wurde mir folgender Fehler angezeigt:
Zugriffsverletzung bei 0x0040597d: Schreiben von Adresse 0x00030cd4. Prozess angehalten.

Mein Quellcode:

Delphi-Quellcode:
procedure TForm1.BTErstellenClick(Sender: TObject);
var i,a:integer;
begin
 setlength(sudoku,80);
 for i:=0 to 80 do
  sudoku[i]:=0;
 randomize;

 a:=random(9)+1;
 sudoku[0]:=a;

 zahl0.Text:=inttostr(sudoku[0]);

 a:=random(9)+1;
 while a=sudoku[0] do
  a:=random(9)+1;
 sudoku[1]:=a;

 zahl1.Text:=inttostr(sudoku[1]);

 a:=random(9)+1;
 while (a=sudoku[0]) or (a=sudoku[1]) do
  a:=random(9)+1;
 sudoku[2]:=a;

 zahl2.Text:=inttostr(sudoku[2]);

 a:=random(9)+1;
 while (a=sudoku[0]) or (a=sudoku[1]) or (a=sudoku[2]) do
  a:=random(9)+1;
 sudoku[3]:=a;

 zahl3.Text:=inttostr(sudoku[3]);

 a:=random(9)+1;
 while (a=sudoku[0]) or (a=sudoku[1]) or (a=sudoku[2]) or (a=sudoku[3]) do
  a:=random(9)+1;
 sudoku[4]:=a;

 zahl4.Text:=inttostr(sudoku[4]);

 a:=random(9)+1;
 while (a=sudoku[0]) or (a=sudoku[1]) or (a=sudoku[2]) or (a=sudoku[3])
        or (a=sudoku[4]) do
  a:=random(9)+1;
 sudoku[5]:=a;

 zahl5.text:=inttostr(sudoku[5]);

 a:=random(9)+1;
 while (a=sudoku[0]) or (a=sudoku[1]) or (a=sudoku[2]) or (a=sudoku[3])
        or (a=sudoku[4]) or (a=sudoku[5]) do
  a:=random(9)+1;
 sudoku[6]:=a;

 a:=random(9)+1;
 while (a=sudoku[0]) or (a=sudoku[1]) or (a=sudoku[2]) or (a=sudoku[3])
        or (a=sudoku[4]) or (a=sudoku[5]) or (a=sudoku[6]) do
  a:=random(9)+1;
 sudoku[7]:=a;

 a:=random(9)+1;
 while (a=sudoku[0]) or (a=sudoku[1]) or (a=sudoku[2]) or (a=sudoku[3])
        or (a=sudoku[4]) or (a=sudoku[5]) or (a=sudoku[6]) or (a=sudoku[7]) do
  a:=random(9)+1;
 sudoku[8]:=a;
end;
Nach "zahl5.text:=inttostr(sudoku[5]);" wird der Fehler angezeigt, wenn ich diese Zeile ans Ende setze, läuft er die anderen Zeilen problemlos durch und zeigt dann wieder den Fehler an. Wenn ich die Zeile komplett weglasse und 2mal auf den Button klicke, dann kommt der Fehler ebenfalls. Sudoku ist ein global vereinbarter array of integer.

Kann mir jemand bitte helfen?

THX im Voraus!

xaromz 30. Jun 2006 09:14

Re: Zugriffsverletzung
 
Hallo,

gleich am Anfang:
Delphi-Quellcode:
setlength(sudoku,80);
for i:=0 to 80 do
  sudoku[i]:=0;
Du erstellst ein Array mit der Länge 80, also von 0 bis 79. Dann greifst Du aber auf das Element #80 zu, das nicht existiert.

Gruß
xaromz

Edit: Herzlich Willkommen!

Gausi 30. Jun 2006 09:16

Re: Zugriffsverletzung
 
Delphi-Quellcode:
setlength(sudoku,80);
for i:=0 to 80 do
- müsste die Länge nicht 81 sein? Ich glaube zwar nicht unbedingt, dass der Fehler daher kommt, aber ein Anfang wärs ;-)

ste_ett 30. Jun 2006 09:40

Re: Zugriffsverletzung
 
Delphi-Quellcode:
  for i := Low(ArrayName) to High(ArrayName) do
  begin
    ...
  end;
Das wäre eine Möglichkeit, solche Fehler nicht zu wiederholen. :)

Bei dynamsichen Arrays ist Low() imemr 0, da kann man sich das dann sparen und gleich 0 nutzen. :)

Chii 30. Jun 2006 09:41

Re: Zugriffsverletzung
 
ihr werdet lachen, aber anscheinend war es das! <3 delphi

Chii 30. Jun 2006 09:58

Re: Zugriffsverletzung
 
so... nun hab ich die zweite zeile hinzugefügt und starte es - was passiert? delphi hängt sich auf!
wenn ich die per haltestops durchgehe, gibt er mir ein ergebnis aus.
was kann ich machen?! :(

ste_ett 30. Jun 2006 10:08

Re: Zugriffsverletzung
 
Evtl. hast du eine Endlosschleife drin.
Prüfe mal im Debugger, ob alle Schleifen korrekt durchlaufen werden.

Chii 30. Jun 2006 10:17

Re: Zugriffsverletzung
 
der debugger zeigt mir keine fehler an, es funktioniert ja auch alles, wenn ich mit haltepunkten durchgehe.

Sidorion 30. Jun 2006 11:01

Re: Zugriffsverletzung
 
Ich will Dich nicht enttäuschen, aber so kommst Du leider nicht weit.
Als Speicher für die Felder würde ich Dir ein Array [0..8,0..8] of Byte vorschlagen.
Das Füllen dieses Arrays würde ich mit Backtracking algorithmus tun.
Die Bedingung dafür dass eine best. Zahl in ein Feld passt, ist ja, dass sie Zahl weder in der selben Reihe, noch in der selben Spalte, noch im selben Feld schonmal steht. Dafür würd ich mir ne funktion schreiben ala ZahlGültig(Zeile, Spalte, Zahl): Boolean.
Jetzt kannst Du folgendermassen vorgehen:
Du gehst dein Array durch, und versuchst das nächste Feld zu füllen (und zwar testest Du zufällig die Zahlen 1-9 und die erste, die geht schreibst Du rein (und merk dir für jedes Feld, welche Zahl schon getestet wurde). KannstDu nun ein Feld mit keiner Zahl füllen (alle neun negativ getestet), musst Du ein Feld zurück, und dort ndie nächste Zahl testen. geht das wieder nicht, dann wieder ein Feld zurück.
Das ganze kannst Du iterativ oder rekursiv lösen, wobei Rekursiv einfacher wäre, wegen dem Merken der getesteten Zahlen, sprich:
Delphi-Quellcode:
SetzeZahl(Zeile, Spalte): Boolean;
wiederhole
 würfle Zahl aus Vorrat und streiche diese aus Vorrat.
 prüfe zahl
solange bis vorrat leer oder prüfung erfolgreich
wenn prüfung erfolgreich,
dann begin
  schreibe Zahl in Array
  wenn Zeile und Spalte <8
  dann begin
   wenn spalte<8
   dann Ergebnis=SetzeZahl(Zeile, Spalte+1)
   sonst Ergebnis=setzeZahl(Zeile+1, 0)
  sonst Ergebnis=Ja
sonst ergebnis=nein


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