Re: Zufallszahl ziehen ohne wiederholung
schöner Spaghetti-code :( und massig units...wozu die 3 leeren units (2-4)?
nachdem ich deine projektdatei geöffnet habe, vermute ich, dass die units auch nicht die richtigen sind (anderer Ordner). lagere mal bitte die fragen+antworten in eine externe Datei (ini,xml,etc) aus, damit das Codesegment universeller und besser lesbarer wird. 36 Schwierigkeitsgrade? ich denke 3 reichen...ist sicher nur unglückliches benamen der variablen. als kleiner tipp am rande...folgendes lässt sich auch entscheidend verkürzen:
Delphi-Quellcode:
z.b. so:
Case Loesung of
1:begin Panel2.Color:=clgreen; Panel3.Visible:=false; Panel4.Visible:=false; Panel5.Visible:=false; end; 2:begin Panel3.Color:=clgreen; Panel2.Visible:=false; Panel4.Visible:=false; Panel5.Visible:=false; end; 3:begin Panel4.Color:=clgreen; Panel2.Visible:=false; Panel3.Visible:=false; Panel5.Visible:=false; end; 4:begin Panel5.Color:=clgreen; Panel2.Visible:=false; Panel4.Visible:=false; Panel3.Visible:=false; end;
Delphi-Quellcode:
oder
var panel:TPanel
Panel2.Visible:=false; Panel3.Visible:=false; Panel4.Visible:=false; Panel5.Visible:=false; panel:=findcomponent('Panel'+IntToStr(Loesung+1)); if assigned(panel) then begin panel.visible:=true; panel.color:=clGreen; end;
Delphi-Quellcode:
einfach so:
case ZS of
1: begin with mediaplayer1 do begin Filename:=Pfad+'\Mediendateien\richtigeAntwort\1.wav'; mediaplayer1.Open; mediaplayer1.Play; end; end; ... //obiger code noch 3x und das bei jedem panelclick.
Delphi-Quellcode:
du kannst mehreren Panels auch die gleiche Click-Prozedur zuweisen...so sparst du redundaten code...
with mediaplayer1 do
begin Filename:=Pfad+'\Mediendateien\richtigeAntwort\'+IntToStr(ZS)+'.wav'; mediaplayer1.Open; mediaplayer1.Play; end; wenn du die paar sachen machst und noch eine bessere Einrückung :) dann wird dein code schonmal viel besser lesbar.warum eigentlich 4 mediaplayer? den Vergleich, ob frage schon gefragt wurde hab ich noch nicht gefunden... Gruß Frank |
Re: Zufallszahl ziehen ohne wiederholung
Sag mal, kann das sein, dass da die falschen Dateien dabei sind? In dem Quelltext nimmst du ja noch eine beliebige Zufallszahl. Im Projekt wird verwiesen auf ein Verzeichnis '..\das was net ging\Delphi Projekt', aber diese Dateien sind leider nicht dabei...
Zum Konzept: Wie wäre es, wenn du die Fragen aus einer Datei lädst oder zumindest konstante Arrays benutzt? So ist das doch viel zu umständlich, wenn du Fragen hinzufügst, etc. // EDIT: Zur Frage "Wo ist der Sitz des Bundeshauses?": Der Sitz des Bundestages ist Berlin und das Bundeshaus steht immer noch in Bonn, wird aber anderweitig verwendet. |
Re: Zufallszahl ziehen ohne wiederholung
Das habe ich auch schon gerade festgestellt, ich werde gleich noch mal die richtigen hochladen
|
Re: Zufallszahl ziehen ohne wiederholung
Da reichen aber die Quelltextdateien, und die kannst du auch hier in den Anhang legen, wer die anderen Dateien dazu will, der kann ja den Link oben benutzen.
|
Re: Zufallszahl ziehen ohne wiederholung
So das hab ich jetzt auch gemacht! Hier ist der Quelltext!
http://rapidshare.com/files/19529755...lli18.rar.html Sorry, ich hätts auch hier hochladen können, is mir aber zu spät eingefallen! Das Problem bleibt immer noch: 1. ich muss den Quelltext redundanter gestalten 2. wieso er in der unit 5 bei button 1 click das mit der zufallszahl z super macht und in der listbox dokumentiert aber genau dasselbe bei form5.button 2. click nicht macht und immer gleich die if bedingung erfüllt was dazu führt, dass er schreibt, sie haben das spiel erfolgreich beendet |
Re: Zufallszahl ziehen ohne wiederholung
Zitat:
Zweitens ist der Quelltext auskommentiert, der die Variable füllt... So geht es bei mir:
Delphi-Quellcode:
procedure TForm5.Button2Click(Sender: TObject);
var p,z,i:integer; //liste: string; begin //////////////////////////////////////////////////////////////////////// Randomize; liste:=''; for i:=1 to gesamt do liste:=liste+chr(i); if length(liste)<=gesamt-anzahl then |
Re: Zufallszahl ziehen ohne wiederholung
Danke jaenicke! Ich bin einen großen Schritt weiter!
Es funktioniert jetzt! Ich hab nur noch das Problem, dass ich ja immer wieder wenn ich eine neue zufallszahl will und die brauche ich 15 mal auf button 2 clicke! und mit dieser variante kommen dann die zufallszahlen doppelt vor, das möchte ich ja aber nicht, da ich keine doppelten fragen haben möchte! Ich denke das liegt daran, dass diese liste immer beim klicken auf button 2 neu erstellt wird, aber wie muss ich den quelltext ändern, damit die ersten 15 zufallszahlen nicht doppelt vorkommen?? Ich hab auch noch nen button für neues spiel, dabei sollten wieder neue zufallszahlen kommen! Was muss ich da eigeben?? |
Re: Zufallszahl ziehen ohne wiederholung
Ach ja, die Initialisierung brauchst du da ja nicht. Die brauchst du dann aber für ein neues Spiel, womit deine zweite Frage beantwortet ist. ;-)
Delphi-Quellcode:
Und einen Fehler: Wenn ich auf Weiter statt eine Antwort klicke wird trotzdem weitergezählt...
procedure TForm5.Button2Click(Sender: TObject);
var p,z,i:integer; begin //////////////////////////////////////////////////////////////////////// Randomize; if length(liste)<=gesamt-anzahl then |
Re: Zufallszahl ziehen ohne wiederholung
dankeschön, soweit habe ich das auch jetzt endlich hinbekommen! Es bleibt noch eine frage! mit neues spiel starten klappt! Das problem ist nur, dass ich button2. click in form5 habe und neues spiel starten in form6 habe! Der quelltext funktioniert (ich hab ihn mal zum neuen Spiel starten in form5 gehauen) aber in form6 kann ich die liste aus form5 net löschen! Was muss ich dafür tun??
Danke für die Antwort! |
Re: Zufallszahl ziehen ohne wiederholung
Weil du die Variable Liste in der implementation Sektion deklariert hast. Damit ist diese nur innerhalb dieser Unit sichtbar. Du kannst die Variable unter public deklarieren, dann kannst du mit Form5.liste auch darauf zugreifen.
|
Re: Zufallszahl ziehen ohne wiederholung
Zitat:
Wenn das Teil in zwei oder mehr Formularen benutzt wird, sollte es in einer extra Unit und nur dort definiert werden, das von allen mit uses aufgenommen wird. Dort und ebenfalls nur dort sollte dann auch eine Procedure für den Neuaufbau implementiert werden. Außerdem am besten auch gleich eine Function, die die gezogene Nummer zurückgibt. Alle anderen Vorkommen von liste gehören dann rausgeschmissen! PS: wenn eine Deklaration so wie beschrieben in eine untergeordnete Unit ausgelagert wird, sollte sie einen etwas aussagekräftigeren Namen als liste bekommen. Damit vermeidet man Mehrfach-Deklarationen, zumindest, wenn man nicht weiter in alle Himmelsrichtungen rumkopiert. |
Re: Zufallszahl ziehen ohne wiederholung
Diese Stilfragen sind bei dem Quelltext auch schon egal...
|
Re: Zufallszahl ziehen ohne wiederholung
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
er soll etwas sinnvolles lernen und nicht seinen Stil noch schlimmer machen...nebenbei bemerkt, hab ich ihm mal ein Beispielprogramm geschrieben, welches ihm zeigt, wie man das ganze mit ~250 Zeilen Quellcode hinbekommt (+externe Fragenaufbewahrung). und da solche Frage-Antwort-Programme schon häufiger ein Thema waren, mal mein Programm im Anhang. aber an alle Anfänger: nicht nur blind kopieren, sondern verstehen :) Gruß Frank |
Re: Zufallszahl ziehen ohne wiederholung
Zitat:
aber vielleicht hilft es ja trotzdem, ein paar Tipps zu geben, wie es besser wäre |
Re: Zufallszahl ziehen ohne wiederholung
Delphi-Quellcode:
type TIntArr = Array of Integer;
... function _Random( Range: Integer; var List: TIntArr ): Integer; var i, x: Integer; begin if Length(List) = 0 then begin SetLength(List, Range); for i := 0 to High(List) do List[i] := i; end; x := Random(Length(List)); Result := List[x]; for I := x+1 to High(List) do list[i-1] := list[i]; SetLength( List, High(List) ); end; ... // der wert "range" wird nur beim ersten aufruf benutzt, und wenn die liste leer ist // wird sie halt neu initialisiert :P // --Klatsch ne Memo und nen Button auf die Form und im OnClick Ereignis schreibst du // --folgendes var x: Integer; i: Integer; begin x := _Random( StrToInt(Edit1.Text), Numbers ); Memo1.Clear; for i := 0 to High(Numbers) do Memo1.Lines.Add( inttostr(i+1) + '.'#9 + IntToStr(Numbers[i]) ); Caption := 'Random Number - ' + IntToStr(X); |
Re: Zufallszahl ziehen ohne wiederholung
|
Re: Zufallszahl ziehen ohne wiederholung
Zitat:
Wie beim Lotto halt...
Delphi-Quellcode:
Procedure Sproideldoing;
var Pottich: TStringList; i, z: integer; begin Pottich := TStringlist.Create; try for i := 1 to 40 do Pottich.Add(IntToStr(i)); for i := 1 to 15 do begin z := random(Pottich.Count); ShowMessage(IntToStr(Pottich[z])); Pottich.Delete(z); end; finally Pottich.Free; end; end; |
Re: Zufallszahl ziehen ohne wiederholung
Zitat:
bitte zahlen nicht in stringlisten verwalten. das ist performancemäßig das ungünstigste, was man machen kann... das sinnvollste der bisherigen Vorschläge ist imho das vermischte array, da es ohne löschen auskommt. da dürfte noch nichtmal eine TList (mit auf TObject gecasteten Integern) rankommen, da es egal ist, ob die Integer-Daten selbst oder Pointer darauf (beides 32-bit-Werte) vertauscht werden. Bei anderen Datentypen dürfte TList schneller sein. Gruß Frank |
Re: Zufallszahl ziehen ohne wiederholung
Zitat:
Same old story, same old song! Don't go right, don't go wrong ;-) |
Re: Zufallszahl ziehen ohne wiederholung
das mit der Performance war nur als Randbemerkung gemeint...es geht hauptsächlich darum, einen passenden Datentyp zu wählen.und zur Verwaltung von Zahlen ist Stringlist nun mal ungeeignet.
Findest du, dass der Ansatz mit dem vermischten array schwerer war? Bei der Verwaltung in einer TList wäre der Code fast genauso wie deiner, nur dass du die Konvertierung sparst und es wesentlich schneller gehen dürfte. Der Lösungsansatz an sich war ja nicht falsch, nur das falsche Werkzeug. du nimmst ja auch nicht die Blumenschaufel (lag gerade griffbereit), um Schnee zu schippen, oder? auch wenns nur die Ausfahrt ist...geht auch, dauert halt nur bisschen länger (blöder Vergleich, aber mir fiel grade nix besseres ein :D) Deine Bemühungen zu helfen möchte ich natürlich anerkennen :) ich bin kein Experte (programmiere auch nur als Hobby),aber das sollte Grundwissen sein. Gerade gegenüber Anfängern sollte man da schon bisschen drauf achten, finde ich...es muss nicht der optimalste Code sein, aber unnötige Typ-Konvertierungen verwirren mehr als das sie nutzen. Gruß Frank |
Re: Zufallszahl ziehen ohne wiederholung
Gute Antwort :-D
Dann gib doch mal ein Beispiel wie mein Code statt einer TStringList mit TList aussähe. Habe noch nie damit gearbeitet. Du hast mich schon fast überzeugt |
Re: Zufallszahl ziehen ohne wiederholung
Delphi-Quellcode:
Wenns mich net täuscht so, nur getippt, nicht propiert :mrgreen:
rocedure Sproideldoing;
var Pottich: TList; i, z: integer; begin Pottich := TList.Create; try for i := 1 to 40 do Pottich.Add(TObject(i)); for i := 1 to 15 do begin z := random(Pottich.Count); ShowMessage(IntToStr(Integer(Pottich[z]))); Pottich.Delete(z); end; finally Pottich.Free; end; end; |
Re: Zufallszahl ziehen ohne wiederholung
aus deinem code mal fix geändert (wie gesagt, viel anders ists nicht):
Delphi-Quellcode:
dein code war übrigends nicht ganz lauffähig... das IntToStr bei der showmessage war zuviel :)
procedure TForm1.Button1Click(Sender: TObject);
var Pottich: TList; i, z: integer; begin Pottich := Tlist.Create; try for i := 1 to 40 do Pottich.Add(TObject(i)); for i := 1 to 15 do begin z := random(Pottich.Count); ShowMessage(IntToStr(Integer(Pottich[z]))); Pottich.Delete(z); end; finally Pottich.Free; end; end; Mist...da war jemand schneller...und das um die Zeit Gute Nacht |
Re: Zufallszahl ziehen ohne wiederholung
Zitat:
Gruß -- |
Re: Zufallszahl ziehen ohne wiederholung
Das selbe Spielchen würde mit einer TStringList auch funktionieren, wenn man AddObject verwendest :mrgreen:
|
Re: Zufallszahl ziehen ohne wiederholung
Ein Variante von mir, schafft auf meinem Rechner 3 Millionen Ziehungen von 6 aus 49 pro Sekunde.
Delphi-Quellcode:
Wenn die Ergebnisse sortiert sein dürften, sähe das noch etwas einfacher aus.
const
CRLF = #13#10; function Lottozahlen(Min, Max: Integer; Count: Word): TIntegerDynArray; {---} procedure Swap(var Value1, Value2: Integer); inline; var Temp: Integer; begin Temp := Value1; Value1 := Value2; Value2 := Temp; end; {---} var diff, i1, i2, r1, r2: Integer; SortArray: TIntegerDynArray; begin diff := Max - Min + 1; if diff < Count then raise Exception.Create(Format('Ungültige Parameter' + CRLF + 'Lottozahlen(%d, %d, %d)', [Min, Max, Count])); SetLength(Result, Count); SetLength(SortArray, Count); for i1 := 0 to Count - 1 do begin r1 := Random(diff) + Min; r2 := r1; for i2 := 0 to i1 - 1 do begin if (r1 = r2) and (SortArray[i2] <= r2) then begin Inc(r1); Inc(r2); end else Swap(r2, SortArray[i2]); end; Result[i1] := r1; SortArray[i1] := r2; Dec(diff); end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:14 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