| Autor |
Beitrag |
at4germany
      
Beiträge: 19
|
Verfasst: Di 18.09.07 18:51
Hallo,
ich habe ein Frage:
und zwar habe ich einen random wert, sagen wir mal 20. Durch random kann ich ja in dem Bereich einen Zufallswert erhalten. Aber nun möchte ich, dass ich nur einmal jeden Wert erhalte, also nicht doppelt, und am ende irgendwie eine Meldung erscheint "Ende". Entweder über ein Label oder ein neues Fenster, wie kann ich das bewerkstelligen? Gibts einen extra befehl dafür?
lg
|
|
Regan
      
Beiträge: 2157
Erhaltene Danke: 72
Java (Eclipse), Python (Sublimetext 3)
|
Verfasst: Di 18.09.07 19:01
Schau dir mal das hier an.
|
|
DasMarX
Hält's aus hier
Beiträge: 3
|
Verfasst: Di 18.09.07 19:31
DAs Zauberwort heißt 'Fisher-Yates'. Such mal hier danach. Im Prinzip nimmt man sich alle Zahlen, die man zufällig aber nur einmal ziehen möchte, mischt sie durch und zieht dann eben nacheinander eine Zahl von dem gemischten Stapel.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 18.09.07 19:38
@DasMarX: Die von mir unter dem genannten Link gepostete Lösung ist für diesen Fall besonders bei m=ZuZiehendeZahlen <<< n=Mögliche Zahlen wesentlich schneller als Fisher-Yates ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
at4germany 
      
Beiträge: 19
|
Verfasst: Mi 19.09.07 14:54
so hab jetzt mal versucht das selber zu schreiben. Nur irgendwo ist noch ein Fehler den ich nicht endecken kann. Delphi meckert immer beim array rum...
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:
| function TForm1.VokDeutsch: string; var s: TStringList; begin s:= TStringList.Create; s.LoadFromFile('D.txt'); d:= s.Count-1; Label7.Caption:=inttostr(d); try result:= s.Strings[d]; finally s.free; end; end;
function TForm1.ArZahl:integer; var i,j: integer; ZFeld: array [1..i] of integer; begin for i:= 1 to d do begin z:= random(d)+1; ZFeld[i]:=z; for j:= 1 to d do begin if z:=ZFeld[i] then z:=random(d); end; result:=z; end; |
lg
|
|
Wonko
      
Beiträge: 69
|
Verfasst: Mi 19.09.07 16:06
Hey,
ich glaube der Fehler liegt darin begraben, wie Du ZFeld deklarierst. Du schreibst ZFeld: array [1..i] of integer;, aber wie groß ist i? Du hast eine Zeile vorher nur gesagt, es gibt einen Integer i; aber nicht initialisiert, also keinen Wert zugewiesen!
Wenn dieser Fehler besitigt ist (evtl. mit einem dynamischen Array), wird es trotzdem nicht tun, was Du willst:
Delphi-Quelltext 1: 2:
| if z:=ZFeld[i] then z:=random(d); |
lässt nur nochmal neu ziehen, aber es kann doch sein, das der selbe Wert gezogen wird, dann ist diese Abfrage völlig nutzlos.
Wenn Dir die repeat-Schleife von Regans Link nicht zusagt, hilft Dir vielleicht ein Post von mir weiter: www.delphi-forum.de/....php?p=445965#445965
Eine weitaus unelegantere Lösung, aber sie wurde angenommen 
_________________ "Read the directions, even if you don't follow them.", Mary Schmich
|
|
at4germany 
      
Beiträge: 19
|
Verfasst: Mi 19.09.07 16:14
Ich würde ja gerne die Lösung aus regans link nehmen, aber mein Problem ist nur ich weiss nicht wie ich das einbauen sollte^^
lg
|
|
JayEff
      
Beiträge: 2971
Windows Vista Ultimate
D7 Enterprise
|
Verfasst: Mi 19.09.07 17:02
_________________ >+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
|
|
alzaimar
      
Beiträge: 2889
Erhaltene Danke: 13
W2000, XP
D6E, BDS2006A, DevExpress
|
Verfasst: Mi 19.09.07 17:15
BenBE hat folgendes geschrieben: | | @DasMarX: Die von mir unter dem genannten Link gepostete Lösung ist für diesen Fall besonders bei m=ZuZiehendeZahlen <<< n=Mögliche Zahlen wesentlich schneller als Fisher-Yates ... |
Hmm..., aber längst nicht so elegant... Die Lösung von Dir ist außerdem nicht allgemeingültig und wird bei n=m und großem m sehr lange dauern, weil ständig bereits gezogene Zufallszahlen ermittelt werden....
_________________ Na denn, dann. Bis dann, denn.
|
|
at4germany 
      
Beiträge: 19
|
Verfasst: Mi 19.09.07 17:27
Ok, ich habe es jetzt geändert.
So sieht es jetzt aus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| function TForm1.ArZahl:integer; var j,i: integer; var arr : array of integer; begin setlength(arr, 65); Arr[i]:= random(d); for i:= 1 to d do begin z:= random(d)+1; Arr[i]:=z; for j:= 1 to d do begin if z=Arr[i] then z:=random(d); end; result:=z; end; end; |
aber es geht leider immer nich nicht. Er zeigt mir eine Zufriffsverletzung der Klasse EAccessViolation an. Un wenn ich das //Arr[i]:= random(d);\\ enferne, compiliert er zwar, aber es erscheint immer nur die selbe Vokabel..
lg
|
|
Kroko
      
Beiträge: 1284
W98 W2k WXP
Turbo D
|
Verfasst: Mi 19.09.07 17:41
dynamische Arrays beginnen bei 0 , also die Schleife von 0 bis d-1!
_________________ Die F1-Taste steht nicht unter Naturschutz und darf somit regelmäßig und oft benutzt werden! oder Wer lesen kann, ist klar im Vorteil!
|
|
JayEff
      
Beiträge: 2971
Windows Vista Ultimate
D7 Enterprise
|
Verfasst: Mi 19.09.07 19:38
Kroko hat folgendes geschrieben: | | dynamische Arrays beginnen bei 0 , also die Schleife von 0 bis d-1! |
vorrausgesetzt d=65 laut deinem Code!
_________________ >+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
|
|
Kroko
      
Beiträge: 1284
W98 W2k WXP
Turbo D
|
Verfasst: Do 20.09.07 05:44
_________________ Die F1-Taste steht nicht unter Naturschutz und darf somit regelmäßig und oft benutzt werden! oder Wer lesen kann, ist klar im Vorteil!
|
|
at4germany 
      
Beiträge: 19
|
Verfasst: Do 20.09.07 16:05
danke, aber fehler bleibt immernoch bestehen... irgendwas stimmt nicht mit dem Arr[i]:= random(d);
auch wenn ich anstelle d 65 eintrag bekomm ich immer noch eine Meldung "zugriffsverletzung"...
|
|
Wonko
      
Beiträge: 69
|
Verfasst: Do 20.09.07 16:36
Ich versuch's nochmal: Du solltest i einen Wert zuweisen.
| Zitat: |
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| var j,i: integer; var arr : array of integer; begin setlength(arr, 65); Arr[i]:= random(d); ... | |
Bisher steht da (u.a.): "es gibt einen Integer mit dem Namen i"; vier Zeilen weiter dann: "das i-te Argument eines Arrays soll einen zufälligen Wert haben", aber wie groß ist i? Ohne Zuweisung durch Dich (oder eine Funktion o.ä.) ist das irgendein zufälliger Integer-Wert, also evtl. viel größer als die Länge des Arrays. Es fehlt also eine Zeile die so ähnlich aussieht:
Delphi-Quelltext wobei i nicht größer sein darf als die Länge des Arrays verringert um eins.
_________________ "Read the directions, even if you don't follow them.", Mary Schmich
|
|
JayEff
      
Beiträge: 2971
Windows Vista Ultimate
D7 Enterprise
|
Verfasst: Do 20.09.07 17:31
at4germany hat folgendes geschrieben: | Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| function TForm1.ArZahl:integer;
var j,i: integer;
var arr : array of integer;
begin
setlength(arr, 65);
Arr[i]:= random(d);
for i:= 1 to d do
begin
z:= random(d)+1;
Arr[i]:=z;
for j:= 1 to d do
begin
if z=Arr[i]
then z:=random(d);
end;
result:=z;
end;
end; | |
Hier steht i als Zählvariable einer forschleife, die Zuweisung ist damit perfekt - Das Problem liegt daran, dass (wie wir schon gesagt haben!!) das dynamische Array von 0(!!) bis d-1 (!!!!) geht. Du weißt dem ersten Element nichts zu)was kein problem ist) und dafür einem nicht existierenden, 66ten Element! (zähl ruhig, von Nummer 0 bis Nummer 65 sind es 66 Elemente  )
Die Schleife muss also von 0 bis d-1 gehen.
Edit: Ah ja, da seh ichs, aus irgendeinem Grund weißt du noch vor der schleife einem Arr[i] eine Zahl zu. Lass diese Zeile weg (Wobei Integer i.d.R. mit 0 initialisiert werden)
_________________ >+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
|
|
at4germany 
      
Beiträge: 19
|
Verfasst: Do 20.09.07 17:57
Ok, danke erstmal für die viele Hilfe
so, hab die Sachen geändert, die mir gesagt wurden. Die Fehlermeldung ist jetzt weg, aber ich bekomm immer noch als Deutsche Vokabel "9969432". Woran kann das liegen?
Hier nochmal der geänderte Quelltext für die Deutsche Vokabel:
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:
| function TForm1.VokDeutsch: string; var s: TStringList; begin s:= TStringList.Create; s.LoadFromFile('D.txt'); d:= s.Count-1; Label7.Caption:=inttostr(d); try result:= s.Strings[d]; finally s.free; end; end;
function TForm1.ArZahl:integer; var j,i: integer; var arr : array of integer; begin setlength(arr, d); for i:= 0 to d-1 do begin z:= random(d)+1; Arr[i]:=z; for j:= 1 to d do begin if z=Arr[i] then z:=random(d); end; result:=z; end; end; |
lg
|
|
Wonko
      
Beiträge: 69
|
Verfasst: Fr 21.09.07 08:26
Hey,
weitere mögliche Fehlerquellen:
- Aufruf von Randomize vergessen?
- z falsch deklariert (global)?
Hast Du Dich schon mal via Debugger schrittweise durch Deinen kompletten Code gehangelt? Dabei kann man toll überprüfen, wie lange die einzelnen Werte den Erwartungen entsprechen und wo Unsinn reinkommt.
Ich verstehe immer noch nicht den Sinn der folgenden Zeilen: | Zitat: | Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| Arr[i]:=z; for j:= 1 to d do begin if z=Arr[i] then z:=random(d); end; | |
Erst weist Du Arr[i] z zu und dann schaust Du, ob z gleich Arr[i] und änderst ggf. z???
@ JayEff: Bei mir ergibt Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| procedure TForm1.FormCreate(Sender: TObject); var i:Integer; begin Label1.Caption:=IntToStr(i); end; | definitiv nicht 0!
Grüße
_________________ "Read the directions, even if you don't follow them.", Mary Schmich
|
|
passiv
      
Beiträge: 270
WIN XP Professional
Delphi 7 Enterprise, Java (Eclipse), Python 2.5, Django 1.1
|
Verfasst: Fr 21.09.07 11:18
wenn ich das richtig verstanden hab, willst du mehr oder weniger lotto machen (oder wir haben das zumindest so gelernt). du musst dir das wie einen Kasten vorstellen (Kasten ist dann das arr: array ...) mit Schubladen mit der Aufschrift der Laufvariable (von arr[i]:=random(d)) und du kannst eine Lade entweder aufmachen oder schließen (arr: array of Boolean -> offen=true, geschlossen=false). so kannst du beim öffnen (also beim belegen) überprüfen (mittels simpelster if-Abfrage) ob denn die Lade eh noch nicht geöffnet ist. und hintendrein läufst du von vorne bis hinten durch und schreibst die zahlen (sortiert sind sie dann auch schon) in ein rein für die Zahlen zuständiges array.
also ich hoff, dass das nicht eine komplett an dem problem vorbeigehende Lösung ist
_________________ Die Probleme, die es in der Welt gibt, sind nicht mit der gleichen Denkweise zu lösen, die sie erzeugt hat.
Albert Einstein
|
|
at4germany 
      
Beiträge: 19
|
Verfasst: Fr 21.09.07 15:51
Ok, also was ich vorhab ist:
Ich möchte via arr Z einen wert zuweisen.
Ob dieser schoneinmal zugewiesen wurde, wird via arr2 überprüft.
Also ich habe z.B. Werte von 0 - 60.
Diese werte sollen per random ausgewählt werden, aber es soll kein wert zweimla ausgwählt werden, d.h. ich bekomme bei der abfrage nicht zweimal den gleichen wert. Wenn ich also 60 vok. habe, sollen diese vokabeln zufällig ausgesucht werde, aber keine soll zweimal abgefragt werden.
So ich hoffe ich habe das jetzt verständlich erklärt
lg
|
|