Autor Beitrag
Vamos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 44



BeitragVerfasst: Di 09.02.10 18:48 
user profile iconGravitar hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconVamos hat folgendes geschrieben Zum zitierten Posting springen:
Hallo Ihr Lieben,

ich wollte mal ein Kartenspiel komplett allein und ohne cards.dll programmieren, um einfach ein bisschen in Delphi rumzuspielen. Bin auch bisher ziemlich zufrieden, läuft soweit alles, nur beim ermitteln und mischen der Karten stürzt mein Programm manchmal ab....


Hi Vamos,

ich programmiere derzeit einen Poker-Wahrscheinlichkeitsrechner. Dort muss man ebenfalls Karten mischen und austeilen.

Derzeit verzichte ich auf das Mischen komplett!!!

Ich ziehe einfach über Random einzelne Karten aus dem Kartenstapel und verteile diese. Wozu noch mischen, wenn ich sowieso über Random ziehe?

Bei ca. 500.000 Hände, die ich simulieren muss, ist der Verzicht auf das Mischen ein enormer Zeitgewinn.

Als Datenkonstrukt nutze ich eine TList of Records (Kartenwert, Kartenfarbe), da ich nach dem Ziehen diese Karte einfach aus der TList löschen kann und damit sichergestellt ist, dass eine Karte nicht mehrfach gezogen wird.

Vielleicht hilft es ja.

Gruß, Andreas


Hi Andreas, danke für den Tipp!

Das meinte ich am Anfrag des Threads, als ich die TList mit einem Objekt verwechselt habe... Wäre pfiffig gewesen, aber ist leider zu spät.

Dennoch muss es doch möglich sein herauszufinden, warum der bei meiner Variante ständig abstürzt...

Es wäre super, wenn jemand das wüsste und mir den entscheidenen Hinweis geben würde.

Es ist echt ätzend das programm immer gleich einige Male starten zu müssen, damit ich neue Funtkionen ausprobieren kann..

Danke nochmals!
Vamos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 44



BeitragVerfasst: Mi 10.02.10 21:29 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconVamos hat folgendes geschrieben Zum zitierten Posting springen:
Naja, zahlen über 48 gibt es bei meiner Radom eingabe zwangsläufig (48 )+11
Schon, aber warum machst du es denn so?

user profile iconVamos hat folgendes geschrieben Zum zitierten Posting springen:
Das habe ich so gestaltet, damit eben keine Zahl < 11 rauskommt.
Ja, und wenn du Zahlen zwischen 11 und 48 willst, dann musst du von der Obergrenze eben die addierte 11 wieder abziehen...
Bei Random(38) + 11 kommen Zahlen von 11 <= Zahl <= 48 heraus.


Oh man, klaro, sorry, hab deinen Beitrag völlig überlesen : (

Nur jetzt wirds noch kurioser...

Bei Random(37)+11 (Karten zwischen 11 und 48 stürzt mein Programm IMMER ab, die entsprechende Filterung wenn zahl > 48 habe ich natrülich rausgenommen.

Bei (38)+11 und der Bedingung zahl = 49 --> dann ungültig, funktioniert es relativ gut mit wenig abstürzen... kann sich da keiner einen Reim Drauf machen?
Vamos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 44



BeitragVerfasst: Mi 10.02.10 22:59 
user profile iconVamos hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconVamos hat folgendes geschrieben Zum zitierten Posting springen:
Naja, zahlen über 48 gibt es bei meiner Radom eingabe zwangsläufig (48 )+11
Schon, aber warum machst du es denn so?

user profile iconVamos hat folgendes geschrieben Zum zitierten Posting springen:
Das habe ich so gestaltet, damit eben keine Zahl < 11 rauskommt.
Ja, und wenn du Zahlen zwischen 11 und 48 willst, dann musst du von der Obergrenze eben die addierte 11 wieder abziehen...
Bei Random(38) + 11 kommen Zahlen von 11 <= Zahl <= 48 heraus.


Oh man, klaro, sorry, hab deinen Beitrag völlig überlesen : (

Nur jetzt wirds noch kurioser...

Bei Random(37)+11 (Karten zwischen 11 und 48 stürzt mein Programm IMMER ab, die entsprechende Filterung wenn zahl > 48 habe ich natrülich rausgenommen.

Bei (38)+11 und der Bedingung zahl = 49 --> dann ungültig, funktioniert es relativ gut mit wenig abstürzen... kann sich da keiner einen Reim Drauf machen?


Btw: Das sagt der Compiler... Kann absolut kein assembler und verstehe nichts...:


Moderiert von user profile iconKha: Bild angehängt.
Einloggen, um Attachments anzusehen!
Xentar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2077
Erhaltene Danke: 2

Win XP
Delphi 5 Ent., Delphi 2007 Prof
BeitragVerfasst: Mi 10.02.10 23:16 
Da bist du nur beim Standard Haltepunkt, wenn man ein Projekt pausiert.. hat also absolut nichts mit deinem Quellcode zu tun.

Aber: Wenn du schon weißt, wo die Endlosschleife entsteht, warum setzt du nicht einfach da einen Haltepunkt, und guckst nach, warum der nicht mehr rauskommt? Dann musst du halt mal 10 Schleifendurchläufe oder so mit verfolgen - na und?

Und bitte sprich nicht von "abstürzen". Für mich ist ein Absturz eher ein richtiger Crash mit Exception und allem was dazu gehört. Was du hier hast, ist einfach ein Einfrieren, verursacht durch eine Endlosschleife.

_________________
PROGRAMMER: A device for converting coffee into software.
Vamos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 44



BeitragVerfasst: Mi 10.02.10 23:20 
user profile iconXentar hat folgendes geschrieben Zum zitierten Posting springen:
Da bist du nur beim Standard Haltepunkt, wenn man ein Projekt pausiert.. hat also absolut nichts mit deinem Quellcode zu tun.

Aber: Wenn du schon weißt, wo die Endlosschleife entsteht, warum setzt du nicht einfach da einen Haltepunkt, und guckst nach, warum der nicht mehr rauskommt? Dann musst du halt mal 10 Schleifendurchläufe oder so mit verfolgen - na und?

Und bitte sprich nicht von "abstürzen". Für mich ist ein Absturz eher ein richtiger Crash mit Exception und allem was dazu gehört. Was du hier hast, ist einfach ein Einfrieren, verursacht durch eine Endlosschleife.


Ich werd mal versuchen...

Wie man einen Haltepunkt setzt ist mir bewust, nur wo ich ihn setzen muss oder vielmehr wo ich gucken soll, warum er nicht aus der Schleife kommt, ist mir nicht klar...

Für mich ist ein Absturz, wenn meine CPU mit 99% der Leistung an meinem Programm rumrechnet... dann geht nichts mehr und ich muss es killen. Aber ich lerne ja dazu : )

Danke für die Antwort.
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 10.02.10 23:22 
Gott, der Bug hat mich fast in den Wahnsinn getrieben :lol: .
Des Rätsels Lösung: Für i=1 wird deine j-Schleife nicht ausgeführt, also kann in zahl[1] eine ungültige Karte landen. Hättest also nur Corpsman folgen und den ungültige-Karte-Test davor setzen müssen ;) :
user profile iconCorpsman hat folgendes geschrieben Zum zitierten Posting springen:
Also was mir ja spontan auffällt, ist das du hier mehrfach auf Zahl[i] in der j schleife zugreifst, d.h. du machst sehr viel doppelt, n-Fach, was total unnütz ist.



user profile iconVamos hat folgendes geschrieben Zum zitierten Posting springen:
Bei Random(37)+11 (Karten zwischen 11 und 48 stürzt mein Programm IMMER ab, die entsprechende Filterung wenn zahl > 48 habe ich natrülich rausgenommen.
Hab doch mal etwas mehr Vertrauen in jaenicke :) . Wie er schon schrieb, [11;48] wird von Random(38) + 11 erzeugt, denn:
ausblenden Delphi-Quelltext
1:
0 <= Random(n) < n					

Mit deinem Code hast du also eine Karte zu wenig und das Array kann nie voll werden.

_________________
>λ=
Vamos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 44



BeitragVerfasst: Mi 10.02.10 23:26 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Gott, der Bug hat mich fast in den Wahnsinn getrieben :lol: .
Des Rätsels Lösung: Für i=1 wird deine j-Schleife nicht ausgeführt, also kann in zahl[1] eine ungültige Karte landen. Hättest also nur Corpsman folgen und den ungültige-Karte-Test davor setzen müssen ;) :

user profile iconCorpsman hat folgendes geschrieben Zum zitierten Posting springen:
Also was mir ja spontan auffällt, ist das du hier mehrfach auf Zahl[i] in der j schleife zugreifst, d.h. du machst sehr viel doppelt, n-Fach, was total unnütz ist.


Ok, super! Mich treibt das auch langsam zum Wahnsinn : ) Weils ja eben sporadisch funktioniert.

Was heißt das im Detail? Wäre jemand so nett und würde mir das umsortieren? Ich wäre so dankbar!!!


user profile iconVamos hat folgendes geschrieben Zum zitierten Posting springen:
Bei Random(37)+11 (Karten zwischen 11 und 48 stürzt mein Programm IMMER ab, die entsprechende Filterung wenn zahl > 48 habe ich natrülich rausgenommen.
Hab doch mal etwas mehr Vertrauen in jaenicke :) . Wie er schon schrieb, [11;48] wird von Random(38) + 11 erzeugt, denn:
ausblenden Delphi-Quelltext
1:
0 <= Random(n) < n					

Mit deinem Code hast du also eine Karte zu wenig und das Array kann nie voll werden.[/quote]

Des hab ich auch gemerkt *schäm* einfaches addieren ist schon Grundvoraussetzung :-S
Vamos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 44



BeitragVerfasst: Sa 13.02.10 18:30 
Es ist zum Wahnsinnig werden, es will einfach nicht funktionieren, ich lande immer wieder bei meiner Bebugten Lösung:

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:
for i := 1 to 32 do
  begin
  randomize;
  repeat
  Zahl[i] := Random(38)+11;


    //2 gleiche Karten vermeiden + verbotene Zahlen vermeiden

  doppelt:=false;
  for j :=1 to i-1 do
    begin
      if Zahl[i] = Zahl[j] then doppelt := true
      else if zahl[i] =19 then doppelt := true
      else if zahl[i] =20 then doppelt := true
      else if zahl[i] =29 then doppelt := true
      else if zahl[i] =30 then doppelt := true
      else if zahl[i] =39 then doppelt := true
      else if zahl[i] =40 then doppelt := true

      else if zahl[j] =19 then doppelt := true
      else if zahl[j] =20 then doppelt := true
      else if zahl[j] =29 then doppelt := true
      else if zahl[j] =30 then doppelt := true
      else if zahl[j] =39 then doppelt := true
      else if zahl[j] =40 then doppelt := true;
      //Wenn zwei Karten doppelt sind, wird die boolsche Variable auf true gesetzt.
    end;

  Until not doppelt;

  LBkarten.Items.Add(IntToStr(zahl[i]));
  // Solange wird gesucht, bis keine doppelten mehr vorkommen, also doppelt:=false!
  end;


Wie muss es ritig ausseen, danke, danke, danke im Voraus
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Sa 13.02.10 18:36 
Ich hatte eigentlich gehofft, diese letzte Überlegung würdest du alleine schaffen. Die Vergleiche ohne zahl[j] müssen aus der Schleife raus, schreib sie davor.

_________________
>λ=


Zuletzt bearbeitet von Kha am Sa 13.02.10 18:37, insgesamt 1-mal bearbeitet
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Sa 13.02.10 18:37 
Möchte nur mal vorschlagen, wie es denn am schnellsten wäre...

Alle Karten in einen Stapel, Fisher-Yates drauf anwenden, und dann der Reihe nach ziehen. Ist eigentlich das einzige was definitv auch in endlicher Zeit terminiert. Und entspricht auch eher einem Spielablauf.

Dein Code läuft potentiell immer in Quasi-Endlosschleifen (da kenn ich mich aus, ist mal ein Map-Generator dran wegestorben), wenn Random einfach mal ungünstige Folgen liefert.

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
Vamos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 44



BeitragVerfasst: Sa 13.02.10 18:40 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Ich hatte eigentlich gehofft, diese letzte Überlegung würdest du alleine schaffen. Die Vergleiche ohne zahl[j] müssen aus der Schleife raus, schreib sie davor.


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:
//Karten mischen

for i := 1 to 32 do
  begin
  randomize;
  repeat
  Zahl[i] := Random(38)+11;
  doppelt:=false;
  if zahl[i] =19 then doppelt := true
  else if zahl[i] =20 then doppelt := true
  else if zahl[i] =29 then doppelt := true
  else if zahl[i] =30 then doppelt := true
  else if zahl[i] =39 then doppelt := true
  else if zahl[i] =40 then doppelt := true;


    //2 gleiche Karten vermeiden + verbotene Zahlen vermeiden


  for j :=1 to i-1 do
    begin
      if Zahl[i] = Zahl[j] then doppelt := true
      else if zahl[j] =19 then doppelt := true
      else if zahl[j] =20 then doppelt := true
      else if zahl[j] =29 then doppelt := true
      else if zahl[j] =30 then doppelt := true
      else if zahl[j] =39 then doppelt := true
      else if zahl[j] =40 then doppelt := true;
      //Wenn zwei Karten doppelt sind, wird die boolsche Variable auf true gesetzt.
    end;

  Until not doppelt;

  LBkarten.Items.Add(IntToStr(zahl[i]));
  // Solange wird gesucht, bis keine doppelten mehr vorkommen, also doppelt:=false!
  end;


?

Edit: Hmmmm, sieht ganz gut aus, muss das leider jetzt er erst 40-50 mal neu starten, da es auch ab und an mal stabil lief. Wenns klappt, kann ich nur nochmal sagen: Danke, danke, danke : )

Sekundär, aber nicht unwichtig, ich versuche immernoch zu verstehen, warum mein Ansatz falsch war, vielleicht nehm ich mir nochmal nen Zettel und nen Stift.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 13.02.10 19:24 
user profile iconVamos hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
  if zahl[i] =19 then doppelt := true
  else if zahl[i] =20 then doppelt := true
  else if zahl[i] =29 then doppelt := true
  else if zahl[i] =30 then doppelt := true
  else if zahl[i] =39 then doppelt := true
  else if zahl[i] =40 then doppelt := true;
Wie wäre es so:
ausblenden Delphi-Quelltext
1:
  doppelt := zahl[i] in [192029303940];					
;-)
Also insgesamt:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
//Karten mischen

for i := 1 to 32 do
begin
  Randomize;
  repeat
    Zahl[i] := Random(38) + 11;
    doppelt := zahl[i] in [192029303940];

    //2 gleiche Karten vermeiden + verbotene Zahlen vermeiden

    for j := 1 to i - 1 do
      if zahl[j] in [zahl[i], 192029303940then
        doppelt := true
      //Wenn zwei Karten doppelt sind, wird die boolsche Variable auf true gesetzt.
  until not doppelt;

  LBkarten.Items.Add(IntToStr(zahl[i]));
  // Solange wird gesucht, bis keine doppelten mehr vorkommen, also doppelt:=false!
end;
Vamos Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 44



BeitragVerfasst: Sa 13.02.10 19:26 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconVamos hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
  if zahl[i] =19 then doppelt := true
  else if zahl[i] =20 then doppelt := true
  else if zahl[i] =29 then doppelt := true
  else if zahl[i] =30 then doppelt := true
  else if zahl[i] =39 then doppelt := true
  else if zahl[i] =40 then doppelt := true;
Wie wäre es so:
ausblenden Delphi-Quelltext
1:
  doppelt := zahl[i] in [192029303940];					
;-)
Also insgesamt:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
//Karten mischen

for i := 1 to 32 do
begin
  Randomize;
  repeat
    Zahl[i] := Random(38) + 11;
    doppelt := zahl[i] in [192029303940];

    //2 gleiche Karten vermeiden + verbotene Zahlen vermeiden

    for j := 1 to i - 1 do
      if zahl[j] in [zahl[i], 192029303940then
        doppelt := true
      //Wenn zwei Karten doppelt sind, wird die boolsche Variable auf true gesetzt.
  until not doppelt;

  LBkarten.Items.Add(IntToStr(zahl[i]));
  // Solange wird gesucht, bis keine doppelten mehr vorkommen, also doppelt:=false!
end;


Cool, danke für den Tipp! "in" hab ich noch nie genutzt, probiere es mal, ist auf jedenfall dann ordentlicher.