Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Skatblatt darstellen durch Random? (https://www.delphipraxis.net/143084-skatblatt-darstellen-durch-random.html)

Lotus 9. Nov 2009 16:38


Skatblatt darstellen durch Random?
 
Hi, ich habe eine Aufgabe bekommen, wo ich scheinbar irgendwie auf dem Schlauch stehe.

Über Math.random werden mir Zahlen zwischen 0,0 und 1,0 (als double) geliefert. Ich soll nun durch diese Zahlen ein Skatblatt simulieren.
Das bedeutet, 32 Karten bzw. Zahlen, wobei
• 4 x 7
• 4 x 8
• 4 x 9
• 4 x 10
• 4 x Bube
• 4 x Dame
• 4 x König
• 4 x As

An sich haette ich jetzt gesagt, da das 8 unterschiedliche Karten sind, nehme ich einfach den Randomwert und schau ob der >0,125 ; > 0,25 ....

Also immer im Abstand von 0,125, da 1,0/8
Allerdings haette ich damit totalen Zufall, was die Karten im Stapel angeht und nicht vorhergesagt, das nur 4x 7 drin is etc..
Wie kann ich das umsetzen?
Evtl könnte ich ja das ganze in einem Zaehler speichern, und immer schauen, ob die Zahl schon 4x vorhanden ist, wenn ja, dann soll neu gewürfelt werden? Habt ihr ne bessere Idee?

himitsu 9. Nov 2009 16:44

Re: Skatblatt darstellen durch Random?
 
Random(32)
0 bis 31

entspricht Trunc(Random * 32)

jetzt würde jede Zahl einer der 32 Karten entsprechen

oder du machst Random(8) und Random(4)
das Erste wäre jetzt die Karte und das Andere die Farbe

Wolfgang Mix 9. Nov 2009 16:46

Re: Skatblatt darstellen durch Random?
 
... oder Random(32) +1

dann haste Zufallszahlen von 1..32

BUG 9. Nov 2009 16:54

Re: Skatblatt darstellen durch Random?
 
Ich glaube es geht hier darum, einen Kartenstapel zu mischen, welcher die oben genannten Karten enthält.
Kann das sein?

Hier im Forum suchenKarten mischen

MfG,
Bug

Lotus 10. Nov 2009 17:04

Re: Skatblatt darstellen durch Random?
 
Wie ich meine Randomwerten bestimmte "Kartenwerte" zuordnen kann, oder wie ich nur einen bestimmten Bereich als mögliche Werte angeben kann ist mir bewusst. Es geht darum, das, falls ich Zahlen von 1-8 Zulasse, jede Zahl nur maximal 4x kommt. Demnach kommt 4x die 2, dann darf kein randomwert mehr die 2 annehmen.. an sich könnte ich eine zählvariable mitlaufen lassen, und jedes mal sagen, wenn i>4 dann neu wuerfeln... allerdings is das einfach mal nich ressourcenfreundlich

sirius 10. Nov 2009 17:30

Re: Skatblatt darstellen durch Random?
 
Ziehen ohne Zurücklegen macht man am Besten mit einer Liste, aus der man das gezogenen Element entfernt.

himitsu 10. Nov 2009 17:32

Re: Skatblatt darstellen durch Random?
 
Zitat:

Zitat von Lotus
Es geht darum, das, falls ich Zahlen von 1-8 Zulasse, jede Zahl nur maximal 4x kommt. Demnach kommt 4x die 2, dann darf kein randomwert mehr die 2 annehmen.. an sich könnte ich eine zählvariable mitlaufen lassen, und jedes mal sagen, wenn i>4 dann neu wuerfeln... allerdings is das einfach mal nich ressourcenfreundlich

Wenn du jede Zahl 4 Mal zuläßt, dann kann es immernoch passieren, daß eine Farbe mehrfach vorkommt.

Nimm dir einfach ein Boolean-Array mit 32 Feldern (je Karte inkl. Farbe ein Feld) und wenn eine Karte gezogen wurde, dann wird diese darin markiert.

Wenn du nun eine neue Karte ziehen willst, dann wähle per Zufall irgendeine der 32 Karten aus,
schaue in dem Array, ob sie noch frei ist
und wenn nicht, dann wird so lange neu gezogen, bis eine freie Karte getroffen wurde.

DeddyH 10. Nov 2009 17:35

Re: Skatblatt darstellen durch Random?
 
Die Listenvariante von sirius dürfte aber deutlich performanter sein. Abgesehen davon würde ich persönlich nicht nachzählen, wie oft eine Zahl gezogen wurde, sondern wie bereits vorgeschlagen 32 Karten nehmen und die Farbe mittels MOD bestimmen.

Lotus 10. Nov 2009 17:39

Re: Skatblatt darstellen durch Random?
 
hab ich vllt vergessen zu erwaehnen, aber die farbe darf vernachlaessigt werden, da nur die kartenwerte interessieren!
das mit dem boolean array hab ich mir auch schon überlegt gehabt, allerdings ist das einfach mal nicht elegant, immer wieder neu zu ziehen bis "zufällig" mal der wert stimmt..

gibts noch andere möglichkeiten außer einer liste?

DeddyH 10. Nov 2009 17:41

Re: Skatblatt darstellen durch Random?
 
Wenn die Farbe keine Rolle spielt, würde ein DIV 8 genügen (bei Werten zwischen 0 und 31).

Lotus 10. Nov 2009 17:45

Re: Skatblatt darstellen durch Random?
 
wuerde allerdings nicht die problematik lösen, das jede zahl nur 4x vorhanden sein darf

DeddyH 10. Nov 2009 17:48

Re: Skatblatt darstellen durch Random?
 
Mit dem erwähnten MOD aber schon (hatte da einen Denkfehler).

Lotus 10. Nov 2009 18:01

Re: Skatblatt darstellen durch Random?
 
inwiefern? das müssteste mir genauer erklaeren

himitsu 10. Nov 2009 18:06

Re: Skatblatt darstellen durch Random?
 
man kann auch das Boolean-Array performant machen und sogar so lösen, daß kein Zug wiederholt werden muß und dieses teilweise sogar performanter, als mit einer rießigen Liste.

das Ziehen:
- man zähle alle "freien" Karten (a)
- x = Random(a)
- nun nehme man einfach die x-te freie Karte davon
- und vergesse nicht sie zu markieren

DeddyH 10. Nov 2009 18:23

Re: Skatblatt darstellen durch Random?
 
Hier ein (nicht optimiertes) Beispiel (Formular enthält eine Listbox und einen Button, mehr nicht):
Delphi-Quellcode:
unit uKarten;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Contnrs;

const MAXINDEX = 31;

type
  TKartenIndex = 0..MAXINDEX;

  TKarte = class
  private
    FIndex: TKartenIndex;
    function GetName: string;
  public
    constructor Create(Index: TKartenIndex);
    property Name: string read GetName;
  end;

  TFrmKarten = class(TForm)
    ListBoxBlatt: TListBox;
    ButtonMischen: TButton;
    procedure ButtonMischenClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  FrmKarten: TFrmKarten;

implementation

{$R *.dfm}

{ TKarte }

constructor TKarte.Create(Index: TKartenIndex);
begin
  inherited Create;
  FIndex := Index;
end;

function TKarte.GetName: string;
const Farben: array[0..3] of string = ('Karo', 'Herz', 'Pik', 'Kreuz');
      Werte: array[0..7] of string = ('7','8','9','10','Bube','Dame','König','As');
begin
  Result := Format('%s %s',[Farben[FIndex div 8],Werte[FIndex mod 8]]);
end;

procedure TFrmKarten.ButtonMischenClick(Sender: TObject);
var Buch, Blatt: TObjectList;
    Karte: TKarte;
    i: integer;
begin
  Buch := TObjectList.Create(false);
  try
    for i := 0 to MAXINDEX do
      begin
        Karte := TKarte.Create(i);
        Buch.Add(Karte);
      end;
    Blatt := TObjectList.Create;
    try
      repeat
        i := Random(Buch.Count);
        Blatt.Add(Buch[i]);
        Buch.Delete(i);
      until Buch.Count < 1;
      for i := 0 to Blatt.Count - 1 do
        ListBoxBlatt.Items.Add(TKarte(Blatt[i]).Name);
    finally
      Blatt.Free;
    end;
  finally
    Buch.Free;
  end;
end;

end.
[edit] Da muss natürlich noch ein Randomize ins OnCreate, hab ich vergessen. [/edit]

Lotus 11. Nov 2009 12:45

Re: Skatblatt darstellen durch Random?
 
was meinst du denn mit nicht optimiert? was wäre denn optimiert?

himitsu 11. Nov 2009 13:23

Re: Skatblatt darstellen durch Random?
 
Delphi-Quellcode:
Type
  TSkatKarte = (
    skKaro7, skKaro8, skKaro9, skKaro10, skKaroBube, skKaroDame, skKaroKoenig, skKaroAs,
    skHerz7, skHerz8, skHerz9, skHerz10, skHerzBube, skHerzDame, skHerzKoenig, skrzAs,
    skPik7,  skPik8,  skPik9,  skPik10,  skPikBube,  skPikDame,  skPikKoenig,  skPikAs,
    skKreuz7, skKreuz8, skKreuz9, skKreuz10, skKreuzBube, skKreuzDame, skKreuzKoenig, skKreuzAs);
  TSkatBlatt = Set of TSkatKarte;
  TSkatFarbe = (sfKaro, sfHerz, sfPik, sfKreuz);
  TSkatWert  = (sw7, sw8, sw9, sw10, swBube, swDame, swKoenig, swAs);

Const sbVollesBlatt = [skKaro7..skKreuzAs];
  ssFarbe: Array[TSkatFarbe] of String = ('Karo', 'Herz', 'Pik', 'Kreuz');
  ssWert: Array[TSkatWert] of String = ('7', '8', '9', '10', 'Bube', 'Dame', 'Koenig', 'As');

Function Skat_Ziehe(Var Blatt: TSkatBlatt): TSkatKarte;
  Var K: TSkatKarte;
    i:  Integer;

  Begin
    If Blatt = [] Then Raise Exception.Create('keine Karten vorhanden');
    i := 0;
    For K := skKaro7 to skKreuzAs do If K in Blatt Then Inc(i);
    i := Random(i);
    Result := TSkatKarte(-1);
    Repeat
      Inc(Result);
      While not (Result in Blatt) do Inc(Result);
      Dec(i);
    Until i < 0;
    Exclude(Blatt, Result);
  End;

Function Skat_Farbe(Karte: TSkatKarte): TSkatFarbe;
  Begin
    Result := TSkatFarbe(Ord(Karte) div 8);
  End;

Function Skat_Wert(Karte: TSkatKarte): TSkatWert;
  Begin
    Result := TSkatWert(Ord(Karte) mod 8);
  End;

Function Skat_String(Karte: TSkatKarte): String;
  Begin
    Result := ssFarbe[Skat_Farbe(Karte)] + ' ' + ssWert[Skat_Wert(Karte)];
  End;

Procedure TForm1.FormCreate(Sender: TObject);
  Var i:  Integer;
    Blatt: TSkatBlatt;
    Karte: TSkatKarte;

  Begin
    Randomize;
    Blatt := sbVollesBlatt;
    For i := 1 to 4 do Begin
      Karte := Skat_Ziehe(Blatt);
      Memo1.Lines.Add(Skat_String(Karte));
    End;
  End;
Schneller geht es nur, wenn man das SET z.B. gegen ein Boolean-Array ersetzt,
aber vom Speicher her, ist dieses das Optimalste, was geht.

sirius 11. Nov 2009 13:31

Re: Skatblatt darstellen durch Random?
 
Zitat:

Zitat von Lotus
was meinst du denn mit nicht optimiert? was wäre denn optimiert?

Es an dein restliches Programm anzupassen. Da kann man dann genau überlgen, wie man die Klassen strukturiert und wie die Schnittstellen aussehen.

Edit: @himi, wir arbeiten doch heute alles objektorientiert. Dein Bitgeschiebe war vor 20 Jahren In. :zwinker:

himitsu 11. Nov 2009 13:32

Re: Skatblatt darstellen durch Random?
 
ach ja, auf das aktuelle Problem zurückgebaut, kommt z.B. sowas bei raus:
Delphi-Quellcode:
Type TBlatt = Set of 0..31;

Const cKarte: Array[0..7] of String = ('7', '8', '9', '10', 'Bube', 'Dame', 'Koenig', 'As');

Function Ziehe(Var Blatt: TBlatt): Integer;
  Var i, i2: Integer;

  Begin
    If Blatt = [] Then Raise Exception.Create('keine Karten vorhanden');
    i := 0;
    For i2 := 0 to 31 do If i2 in Blatt Then Inc(i);
    i := Random(i);
    i2 := -1;
    Repeat
      Inc(i2);
      While not (i2 in Blatt) do Inc(i2);
      Dec(i);
    Until i < 0;
    Exclude(Blatt, i2);
    Result := i2 div 4;
  End;

Procedure TForm1.FormCreate(Sender: TObject);
  Var i, i2: Integer;
    Blatt: TBlatt;

  Begin
    Randomize;
    Blatt := [0..31];
    For i := 1 to 32 do Begin
      i2 := Ziehe(Blatt);
      Memo1.Lines.Add(cKarte[i2]);
    End;
  End;

Lotus 11. Nov 2009 13:37

Re: Skatblatt darstellen durch Random?
 
ah gut.. ich werd mir das ganze in ruhe anschauen und durchgehen, evtl komm ich später nochmal drauf zurück falls fragen auftreten :)

erstmal vielen vielen dank für eure hilfe, denke ddas ich damit was anfangen kann

DeddyH 11. Nov 2009 14:41

Re: Skatblatt darstellen durch Random?
 
Zitat:

Zitat von sirius
Edit: @himi, wir arbeiten doch heute alles objektorientiert. Dein Bitgeschiebe war vor 20 Jahren In. :zwinker:

Tja, diese ewig Gestrigen, da machste nix dran :mrgreen:

himitsu 11. Nov 2009 14:55

Re: Skatblatt darstellen durch Random?
 
Wieso?
Ich seh es nur nicht ein, daß man für jeden Piepselkram gleich mit Objektkanonen rumballern muß. :tongue:

OK, wenn ihr es so wollt ... man kann auch jeden Integer, Byte, Boolean und String einzeln in Klassen verpacken,
aber dann sind die Programme gleich 200-mal größer und langsamer.

sirius 11. Nov 2009 14:57

Re: Skatblatt darstellen durch Random?
 
Zitat:

Zitat von himitsu
OK, wenn ihr es so wollt ... man kann auch jeden Integer, Byte, Boolean und String einzeln in Klassen verpacken,
aber dann sind die Programme gleich 200-mal größer und langsamer.

...und laufen nur mit einer JRE :stupid:


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