Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - "random" funktioniert nicht


DMDADKT - Mo 01.09.08 22:03
Titel: "random" funktioniert nicht
moin leute!
ich hab hier mal ein kleines problem. und zwar habe ich diesen code hier:


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:
var
  n, i, j: integer;
  erl: char;
  volk: array[1..8of integer;
  versch: boolean;

begin
  writeln('Willkommen beim ultimativen "Warhammer 40k: Soulstorm" Zufallsvolkausgeber!');
  writeln;
  write('Spielerzahl:  '); readln(n);
  write('Sind gleiche Voelker erlaubt? (y/n)  '); readln(erl);
  writeln;
  randomize;
  for i:=1 to n do
  begin
//keine gleichen
    if erl='n' then
      repeat
        volk[i]:=(random(n));
        versch:=true;
        for j:=1 to (i-1do
          if volk[i] = volk[j] then versch:= false
      until versch=true
//auch gleiche
    else
      volk[i]:=(random(n));
    case volk[i] of
      0: writeln('Spieler ' + inttostr(i) + ': Space Marines');
      1: writeln('Spieler ' + inttostr(i) + ': Eldar');
      2: writeln('Spieler ' + inttostr(i) + ': Chaos Space Marines');
      3: writeln('Spieler ' + inttostr(i) + ': Orks');
      4: writeln('Spieler ' + inttostr(i) + ': Imperiale Armee');
      5: writeln('Spieler ' + inttostr(i) + ': Tau');
      6: writeln('Spieler ' + inttostr(i) + ': Necrons');
      7: writeln('Spieler ' + inttostr(i) + ': Adeptus Sororitas');
      8: writeln('Spieler ' + inttostr(i) + ': Dark Eldar');
    end;
end.


er soll eigentlich dazu dienen, jeweils ein zufälliges unter 9 völkern in einem spiel für eine beliebige anzahl spieler auszugeben. dabei kann man sich entscheiden, ob gleiche völker möglich sind oder nicht.
allerdings erhalte ich zb bei der auswahl -2 spieler - selbe teams möglich- immer wieder 2 space marines, 2 eldar oder einen space marine und einen eldar als ausgabe.
was stimmt nicht mit der zufälligkeit?

danke und gruß, dmdadkt

Moderiert von user profile iconChristian S.: Code- durch Delphi-Tags ersetzt


Hidden - Mo 01.09.08 22:06

Suche in der Entwickler-Ecke RANDOMIZE


Xentar - Mo 01.09.08 22:08

Ruf das Randomize mal ganz am Anfang auf, bevor du irgendwas ausgibst.

@Hidden: Hab ich auch zuerst gedacht, aber er hats drin ;)


Narses - Mo 01.09.08 22:10
Titel: Re: "random" funktioniert nicht
Moin!

user profile iconDMDADKT hat folgendes geschrieben:

Delphi-Quelltext
1:
2:
3:
  write('Spielerzahl:  '); readln(n);
//...
        volk[i]:=(random(n));
Das n steht doch für die Anzahl Spieler, und nicht für die Völkeranzahl, oder? :?

cu
Narses


Hidden - Mo 01.09.08 22:11

user profile iconXentar hat folgendes geschrieben:
Ruf das Randomize mal ganz am Anfang auf, bevor du irgendwas ausgibst.

@Hidden: Hab ich auch zuerst gedacht, aber er hats drin ;)

Ups, den Fall hielt ich für so klar. Sry :)


DMDADKT - Mo 01.09.08 22:13
Titel: Re: "random" funktioniert nicht
user profile iconNarses hat folgendes geschrieben:
Moin!

user profile iconDMDADKT hat folgendes geschrieben:

Delphi-Quelltext
1:
2:
3:
  write('Spielerzahl:  '); readln(n);
//...
        volk[i]:=(random(n));
Das n steht doch für die Anzahl Spieler, und nicht für die Völkeranzahl, oder? :?

cu
Narses


du hast recht!
habs korregiert, problem bleibt aber bestehn..


aber danke schonmal für die antworten!
und @hidden: gesucht habe ich bereits :/


Edit: yay! es hat wirklich geholfen das randomize ganz an den anfang zu setzen! ich dacht ich hötte das schonmal versucht :P
vielen dank!


Narses - Mo 01.09.08 22:17
Titel: Re: "random" funktioniert nicht
Moin!

user profile iconDMDADKT hat folgendes geschrieben:
du hast recht!
habs korregiert, problem bleibt aber bestehn..
Dann würde ich doch gerne mal die "Korrektur" sehen. ;)

user profile iconDMDADKT hat folgendes geschrieben:
Edit: yay! es hat wirklich geholfen das randomize ganz an den anfang zu setzen! ich dacht ich hötte das schonmal versucht :P
Das kann ich mir nicht vorstellen, setz das Randomize; mal wieder zurück, wo es vorher stand, das sollte keinen Unterschied machen! :)

cu
Narses


Xentar - Mo 01.09.08 23:30
Titel: Re: "random" funktioniert nicht
user profile iconNarses hat folgendes geschrieben:
user profile iconDMDADKT hat folgendes geschrieben:
Edit: yay! es hat wirklich geholfen das randomize ganz an den anfang zu setzen! ich dacht ich hötte das schonmal versucht :P
Das kann ich mir nicht vorstellen, setz das Randomize; mal wieder zurück, wo es vorher stand, das sollte keinen Unterschied machen! :)


Meine Erklärung hierfür:
Random basiert auf der Systemzeit.
So, wie es vorher da stand, war die Zeit zwischen der Ausführung Randomize; und Random(n); immer gleich, weil der Prozessor ja nicht langsamer wurde. Dadurch hatte man hier keinen "zufälligen" Wert bei -> immer das gleiche Ergebnis.

Wenn Randomize nun ganz am anfang aufgerufen wird, hat man einen zufälligen Wert: Nämlich die Zeit, die der Anwender braucht, bis er eine Eingabe tätigt.


Narses - Mo 01.09.08 23:58
Titel: Re: "random" funktioniert nicht
Moin!

user profile iconXentar hat folgendes geschrieben:
Meine Erklärung hierfür:
...ist falsch. ;)

Beweis:

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:
const
  VolkStr: array[0..8of String = ('Space Marines','Eldar','Chaos Space Marines',
    'Orks','Imperiale Armee','Tau','Necrons','Adeptus Sororitas','Dark Eldar');

var
  n, i, j: Integer;
  Duplikate: Char;
  Volk: array[1..9of Integer;
  Doppelt: Boolean;

begin
  Writeln('Willkommen beim ultimativen "Warhammer 40k: Soulstorm" Zufallsvolkausgeber!');
  Writeln;
  Write('Spielerzahl (1..9):  ');
  Readln(n);
  Write('Sind gleiche Voelker erlaubt? (y/n)  ');
  Readln(Duplikate);
  Writeln;
  Randomize; // kann an beliebiger Stelle vor der Schleife stehen, einfach mal probieren :)
  for i := 1 to n do begin
    repeat
      Volk[i] := Random(9);
      Doppelt := FALSE;
      if (UpCase(Duplikate) = 'N'then // Duplikate ausschließen?
        for j := 1 to (i-1do
          Doppelt := Doppelt or (Volk[i] = Volk[j]);
    until NOT Doppelt;
    Writeln('Spieler '+IntToStr(i)+': '+VolkStr[Volk[i]]);
  end;
  ReadLn;
Es muss an einer anderen Änderung an seinem Code gelegen haben (der eine oder andere Anfänger soll ja schon mehrfach darüber gestolpert sein, gleich mehrere Änderungen auf einmal zu machen und dann nicht mehr zu wissen, an welcher Änderung es gelegen hat... :D)

cu
Narses


Xentar - Di 02.09.08 10:15
Titel: Re: "random" funktioniert nicht
user profile iconNarses hat folgendes geschrieben:
Moin!
user profile iconXentar hat folgendes geschrieben:
Meine Erklärung hierfür:
...ist falsch. ;)


Ach verdammt, hast Recht ;)
Dabei hab ich mir soviel Mühe gegeben, beim Ausdenken :(


baka0815 - Di 02.09.08 10:59

RandomErrorNotEnoughRandom [http://thedailywtf.com/Articles/Sampo-UhOh.aspx]?


DMDADKT - Di 02.09.08 16:33

hrm, das ist komisch. schaut euch mal meine version an(anhang). sieht random aus, oder?

hier nochmal der code zum notfalls selberkompilieren.


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:
var
  n, i, j: integer;
  erl: char;
  volk: array[1..8of integer;
  versch: boolean;

begin
  randomize;
  writeln('Willkommen beim ultimativen "Warhammer 40k: Soulstorm" Zufallsvolkausgeber!');
  writeln;
  write('Spielerzahl:  '); readln(n);
  write('Sind gleiche Voelker erlaubt? (y/n)  '); readln(erl);
  writeln;
  for i:=1 to n do
  begin
//keine gleichen
    if erl='n' then
      repeat
        volk[i]:=(random(9));
        versch:=true;
        for j:=1 to (i-1do
          if volk[i] = volk[j] then versch:= false
      until versch=true
//auch gleiche
    else
      volk[i]:=(random(9));
    case volk[i] of
      0: writeln('Spieler ' + inttostr(i) + ': Space Marines');
      1: writeln('Spieler ' + inttostr(i) + ': Eldar');
      2: writeln('Spieler ' + inttostr(i) + ': Chaos Space Marines');
      3: writeln('Spieler ' + inttostr(i) + ': Orks');
      4: writeln('Spieler ' + inttostr(i) + ': Imperiale Armee');
      5: writeln('Spieler ' + inttostr(i) + ': Tau');
      6: writeln('Spieler ' + inttostr(i) + ': Necrons');
      7: writeln('Spieler ' + inttostr(i) + ': Adeptus Sororitas');
      8: writeln('Spieler ' + inttostr(i) + ': Dark Eldar');
    end;
  end;
  writeln;
  writeln;
  writeln;
  writeln('\o/');
  writeln(' |     lulz');
  writeln('/ \');
  readln;
end.



danke für die netten hilfen (:
(btw: warum bekomme ich eigentlich keine mail wenn ich das thema beobachte und eigentlich alles passend eingestellt habe?)


edit: @narses: du hast es nur optimiert, oder? ich sehe jetzt nichts was irgendwas besser macht, oder irre ich mich da? deswegen hab ich es jetzt grade rstmal nicht übernommen


Narses - Di 02.09.08 17:19

Moin!

user profile iconDMDADKT hat folgendes geschrieben:
hrm, das ist komisch. schaut euch mal meine version an(anhang).
Was ist komisch? :gruebel:

user profile iconDMDADKT hat folgendes geschrieben:
sieht random aus, oder?
Nein, eher wie Quelltext... 8)

user profile iconDMDADKT hat folgendes geschrieben:
du hast es nur optimiert, oder?
Ja, es sollte keinen funktionalen Unterschied geben.

user profile iconDMDADKT hat folgendes geschrieben:
ich sehe jetzt nichts was irgendwas besser macht, oder irre ich mich da?
Wenn du das Mischen ohne Duplikate "besser" machen willst, dann schau dir das mal an [http://www.delphi-library.de/topic_perfektes+Mischen+nach+FisherYates+perfect+shuffle_71713.html]. :idea: ;)

cu
Narses