Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi draw poker, hand erkennung (https://www.delphipraxis.net/84023-draw-poker-hand-erkennung.html)

schmog 10. Jan 2007 10:07


draw poker, hand erkennung
 
tach,
ich bin dabei ein Draw Poker zu programmieren und ich frage mich ob man die handerkennung irgendwie vereinfachen kann
und net für jede karte also *.jpg den wert reinschreiben muss und dann noch für die verschiedenen farben wieder eine neue
hand schreiben muss um das zu überprüfen

für hilfe wär ich dankbar
programmier in delphi 7

Der_Unwissende 12. Jan 2007 10:47

Re: draw poker, hand erkennung
 
Hi und herzlich Willkommen in der DP :dp:

Was deine Frage angeht, so bin ich mir ehrlich gesagt nicht ganz sicher, was Du eigentlich genau gefragt hast. Versteh mich nicht falsch! Ich möchte damit nur sagen, dass die meisten Leute hier Dir gerne helfen werden, wenn sie können! Nur solltest Du dabei immer daran denken, dass keiner dein Problem so gut kennt wie Du. Damit andere also verstehen, was Du eigentlich machen möchtest, solltest Du dir immer ein paar Minuten mehr Zeit nehmen (die schnelleren und gezielteren Antworten machen den Aufwand schnell wett) und dein Problem einfach und ausführlich schildern.
Satzzeichen sind da schon mal ein guter Anfang (sehe nur eins hinter "tach") :mrgreen:

Aber mal zum Problem, erstmal schauen ob ich das richtig verstanden habe:
Du programmierst ein Pokerspiel (soweit so klar). Hier möchtest Du den Wert eines Blatts/einer Hand ermittlen? Das verstehe ich jetzt unter Handerkennung, aber wie Du vielleicht schon raushörst, so richtig sicher bin ich mir nicht. Da wäre es dann (für's nächste mal) schöner, wenn Du solche Begriffe ruhig erklärst (nur als Tipp gemeint, erhöht die Wahrscheinlichkeit, dass Dir jmd. hilft).
Die Frage die Du hier stellst ist, ob man diese Erkennung vereinfachen kann. Ob etwas nun einfacher ist oder nicht, dass kann kaum Pauschal gesagt werden, da müsste man schon Deinen bisherigen Ansatz als Relation betrachten. Den hast Du aber nicht wirklich klar geschildert.

Du hast (bisher) eine Karte, die bei Dir als JPEG repräsentiert wird? Das ist eher schlecht. Du solltest hier ganz klar die Darstellung (JPEG) von der Logik (Karte, Blatt, ...) trennen. Das ermöglicht Dir einfach, dass Du die Bilder beliebig austauschen kannst, ohne dass Du dafür dein Spiel verändern musst. Aber auch umgekehrt kannst Du die Kartenbilder für ganz andere Programme verwenden, die vielleicht ihre Karten ganz anders speichern. Ersteres ist dabei durchaus üblicher, i.d.R. ändert sich eher die Darstellung (z.B. mittels Skins o.Ä.).
Wie gesagt, wie eine Karte bei Dir aussieht ändert nichts daran, dass 5 mal die gleiche Farbe ein Flush ist.

Deswegen kannst Du für die Logik einen einfachen Datentypen erstellen, der einfach die Farbe und den Wert einer Karte speichert. Für die Spieler merkst Du dir dann einfach nur in dieser Form ihr Blatt. Für die Anzeige kannst Du dann einfach auf eine Klasse zurückgreifen, die dir zu einer Karte ein Bild zeichnet. Hier kann dann später die graphische Repräsentation ausgetauscht werden.

Für die Logik, was für einen Wert das Blatt hat, kannst du jetzt ganz einfach mit den Karten arbeiten. Geh einfach das Blatt durch und überprüfe (von oben nach unten) was Du im Blatt findest. Du kannst z.B. einfach schauen, ob viermal der gleiche Wert im Blatt ist, natürlich wird das Blatt auch einen Drilling und sogar zwei Zwillinge enthalten, aber das braucht dich nicht mehr zu interessieren!

Die Werte kannst Du dabei dann einfach direkt vergleichen, mal ein wenig im Beispiel:
Delphi-Quellcode:
type
  TKartenWert = 1..13; // 1 = AS, 11 = Bube, 12 = Dame, 13 = König
  TKartenFarbe = (kfKaro, kfHerz, kfPik, kfKreuz);

  TKarte = class(TObject)
    private
      FWert: TKartenWert;
      FFarbe: TKartenFarbe;
    ...
    public
      ...
      property Wert: TKartenwert read FWert;
      property Farbe: TKartenFarbe read FFarbe;
  end;

....
Für die eigentliche Auswertung hast Du dann zwei Möglichkeiten. Du kannst zwei Blätter paarweise in einer Methode vergleichen und hier einfach das stärkere zurückgeben oder Du lässt Dir den Wert einer Hand zurückgeben und vergleichst woanders (was dann aber die Unterscheidung zwischen einzelnen Päarchen, Drillingen, ...) nötig macht.
Der erste Weg sollte also der einfachere sein. Hier kannst Du einfach die Properties Wert und Farbe vergleichen (der Einfachheit halber gehe ich mal von nach Wert Sortierten Blättern aus, kannst Du ja leicht machen):

Delphi-Quellcode:
TBlatt = Array[1..5] of TKarte;

function isFlush(const Blatt: TBlatt): Boolean;
begin
  result := (Blatt[1] = Blatt[2]) and (Blatt[2] = Blatt[3]) and
            (Blatt[3] = Blatt[4]) and (Blatt[4] = Blatt[5]);
end;

function isStraight(const Blatt: TBlatt): Boolean;
begin
  // Zur Erinnerung, es wird von Sortierten Blättern ausgegangen!
  result := (Blatt[2].Wert = succ(Blatt[1].Wert)) and
            (Blatt[3].Wert = succ(Blatt[2].Wert)) and
            (Blatt[4].Wert = succ(Blatt[3].Wert)) and
            (Blatt[5].Wert = succ(Blatt[4].Wert)) and
end;

function isStraightFlush(const Blatt: TBlatt): Boolean;
begin
  result := isFlush(Blatt) and isStraight(Blatt);
end;

function isRoyalFlush(const Blatt: TBlatt): Boolean;
begin
  result := isStraightFlush(Blatt) and (Blatt[1] = 10);
end;

// usw.
So könntest Du jetzt völlig unabhängig von den eigentlichen Werten und Farben feststellen, was Du hier für eine Wertigkeit hast. Natürlich ist das hier noch nicht der vollständige Vergleich. Der müsste daraus bestehen, dass Du die Blätter paarweise prüfst und hier das höchste extrahierst. Sind zwei Blätter nach den Kriterien hier gleichwertig (z.B. zweimal ein Flush), dann muss hier noch zusätzlich geprüft werden, ob eines der Blätter eine höhere Karte besitzt als das andere.
Aufpassen musst Du auch noch beim FullHouse, die Prüfung nach Päarchen und Drilling würde natürlich auch beim Drilling/Vierling wahr sein (da die beides erfüllen!), hier muss also wirklich auf unterschiedliche Werte geprüft werden.

Hoffe aber, dass die Idee grob klar ist (kann aber nicht sagen, ob das einfacher ist als Du es bisher machst).

Gruß Der Unwissende

zecke 1. Mär 2007 17:10

Re: draw poker, hand erkennung
 
:hi:

Ich habe mal deinen Code herumgetestet, speziell um mir anzuschauen, wie das dem Deklarieren einer Klasse etc. funktioniert. Dafür eignet sich dein Ausschnitt bisher hervorragend ;)

Meine Frage dazu: Wie kann ich denn die Kartenwerte in die Variablen schreiben?

Ich habe bisher ein bisschen herummodifiziert, was aber nicht funktioniert (Exception, Zugriffsverletzung):
Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

type
  TKartenWert = 1..13; // 1 = AS, 11 = Bube, 12 = Dame, 13 = König
  TKartenFarbe = (kfKaro, kfHerz, kfPik, kfKreuz);
  TKartenPosition = 1..5;

  TKarte = class(TObject)
    private
      FWert: TKartenWert;
      FFarbe: TKartenFarbe;
      FPosition: TKartenPosition;
    public
      property RWert: TKartenwert read FWert;
      property RFarbe: TKartenFarbe read FFarbe;
      property RPosition: TKartenPosition read FPosition;
      property WWert: TKartenwert write FWert;
      property WFarbe: TKartenFarbe write FFarbe;
      property WPosition: TKartenPosition write FPosition;

end;

var
  Form1: TForm1;
  TBlatt: Array[1..5] of TKarte;

implementation

{$R *.dfm}

function isOnePair():Boolean;
begin
  result := ((TBlatt[1].RWert = TBlatt[2].RWert) and (TBlatt[1].RWert <> TBlatt[3].RWert));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
TBlatt[1].WWert:=1;
TBlatt[1].WFarbe:=kfKaro;
TBlatt[1].WPosition:=1;
{
TBlatt[2].WWert:=2;
TBlatt[2].WFarbe:=kfKaro;
TBlatt[2].WPosition:=2;

TBlatt[3].WWert:=3;
TBlatt[3].WFarbe:=kfKaro;
TBlatt[3].WPosition:=3;

TBlatt[4].WWert:=4;
TBlatt[4].WFarbe:=kfKaro;
TBlatt[4].WPosition:=4;

TBlatt[5].WWert:=5;
TBlatt[5].WFarbe:=kfKaro;
TBlatt[5].WPosition:=5;
}

isOnePair();
end;

end.
Mir ist übrigens klar, dass isOnePair nur die 1. beiden Karten auf ein Paar prüft und nur die 1. drei Karten brücksichtigt.


Wäre nett, wenn mir jemand helfen könnte, das System zu verstehen :mrgreen:

Ich probiere und probiere, aber es will nicht so recht.

Cöster 1. Mär 2007 17:24

Re: draw poker, hand erkennung
 
Delphi-Quellcode:
property RWert: TKartenwert read FWert;
property RFarbe: TKartenFarbe read FFarbe;
property RPosition: TKartenPosition read FPosition;
property WWert: TKartenwert write FWert;
property WFarbe: TKartenFarbe write FFarbe;
property WPosition: TKartenPosition write FPosition;
lässt sich vereinfachen durch

Delphi-Quellcode:
property Wert: TKartenwert read FWert write FWert;
property Farbe: TKartenFarbe read FFarbe write FFarbe;
property Position: TKartenPosition read FPosition write FPosition;
Zitat:

Zitat von zecke
Exception, Zugriffsverletzung

Wo?

zecke 1. Mär 2007 17:25

Re: draw poker, hand erkennung
 
:hi:

Danke schon mal für den 1. Tipp!

Die Exception kommt direkt bei der 1. Zuweisung des Wertes:
Delphi-Quellcode:
TBlatt[1].WWert:=1;

yankee 1. Mär 2007 17:36

Re: draw poker, hand erkennung
 
nur mal so am Rande:
mit Windows' cards.dll kann man sich die Karten auch dirfekt auf ein Canvas an eine beliebige Position zeichnen lassen...
Die haben natürlich auch wieder ihr nummerierungssystem...

zecke 1. Mär 2007 17:39

Re: draw poker, hand erkennung
 
Ja die cards.dll kenne ich, wollte sie aber nicht verwenden. Ich arbeite JPG's und will es damit realisieren :)

Cöster 1. Mär 2007 17:59

Re: draw poker, hand erkennung
 
Zitat:

Zitat von zecke
Die Exception kommt direkt bei der 1. Zuweisung des Wertes:
Delphi-Quellcode:
TBlatt[1].WWert:=1;

Bevor du auf die Eigenschaften eines Objektes zugreifen kannst, musst du es instanzieren, d.h. seinen Konstruktor aufrufen. Weitere Infos zum Umgang mit Klassen siehe hier

zecke 1. Mär 2007 18:54

Re: draw poker, hand erkennung
 
:hi:

Danke! Das hat schon mal ordentlich weitergeholfen. Im Grunde hängt es bisher nur noch and er Deklaration von TKartenFarbe.

Der obere Teil:
Delphi-Quellcode:
  TKartenWert = 1..13; // 1 = AS, 11 = Bube, 12 = Dame, 13 = König
  TKartenFarbe = (kfKaro, kfHerz, kfPik, kfKreuz);
  TKartenPosition = 1..5;
Der public-Teil mit cunstructor:
Delphi-Quellcode:
public
      constructor Create(TKartenWert,TKartenPosition : integer; TKartenFarbe : string);
      property Wert: TKartenWert read FWert write FWert;
      property Farbe: TKartenFarbe read FFarbe write FFarbe;
      property Position: TKartenPosition read FPosition write FPosition;
Dann wie im Tutorial den Cunstructor im Hauptteil:
Delphi-Quellcode:
constructor TKarte.create(TKartenWert,TKartenPosition : integer; TKartenFarbe : string);
begin
  inherited create;
  TKartenWert := Wert;
  TKartenPosition := Position;
  TKartenFarbe := Farbe;          //hier meckert er inkompatible Typen
end;
Bei dieser Konstellation meckert er, "inkompatible Typen TKartenFarbe und string".

Als was muss ich denn TKartenFarbe deklarieren?

"TKartenPosition = 1..5" sah sehr nach integer aus, ebenso wie TKartenWert. Zuerst versuchte ich TKartenFarbe als string zu behandeln, aber das ging nicht.

Wenn ich mit der Maus einzeln über "(kfKaro, kfHerz, kfPik, kfKreuz);" (ganz oben bei der 1. Deklaration von TKartenFarbe) erhalte ich immerhin folgende Hints:

Zitat:

kfKaro Constant - Unit1.pas(21,19)
kfKaro = 0 - Unit1.TKartenFarbe
Zitat:

kfHerz Constant - Unit1.pas(21,27)
kfHerz = 1 - Unit1.TKartenFarbe
Zitat:

kfPik Constant - Unit1.pas(21,35)
kfPik = 2 - Unit1.TKartenFarbe
Zitat:

kfKreuz Constant - Unit1.pas(21,42)
kfKreuz = 3 - Unit1.TKartenFarbe
0,1,2 und 3. Das erinnerte mich an einen Index und ich versuchte es als integer zu behandeln. Das quasi beim Aufrufen, für Karo eine 0 steht, für Herz eine 1, etc...

Das scheint aber nicht so zu sein :gruebel: Das Tutorial konnte mir nicht weiterhelfen oder ich habe da etwas falsch verstanden :?

Bin schon dankbar, aber noch dankbarer über weitere Hilfe :cry:

Cöster 1. Mär 2007 19:19

Re: draw poker, hand erkennung
 
Delphi-Quellcode:
TKartenWert = 1..13; // 1 = AS, 11 = Bube, 12 = Dame, 13 = König
TKartenFarbe = (kfKaro, kfHerz, kfPik, kfKreuz);
TKartenPosition = 1..5;
Hierdurch wurden drei Typen deklariert. Integer ist auch ein Typ, nur dass man den nichtmehr selbst deklarieren muss. Die Variablen und Parameter sollten dann nicht den Namen, sondern den Typen TKartenFarbe o.ä. haben. Man deklariert ja auch keine Variablen namens Integer, sie sind höchstens vom Typ Integer. Die meisten Typen beginnen mit dem Präfix "T", wenn man einen Typen (Integer ist da eine der ganz wenigen Ausnahmen). Die Parameter- und Variablennamen sollten deswegen nicht auch mit T anfangen. Das führt nur zu Verwirrung.

Du müsstest deinen Konstruktor so umschreiben:

Delphi-Quellcode:
constructor TKarte.create(Wert: TKartenWert; Position: TKartenPosition; Farbe: TKartenFarbe);
begin
  inherited create;
  FWert := Wert;
  FPosition := Position;
  FFarbe := Farbe;
end;
Das heißt es wird ein Parameter Namens Wert vom Typ TKartenWert übergeben. Das Feld deiner Klasse namens FWert ist ebenfalls vom Typen TKartenWert.

Weiß nicht, ob's klar geworden ist, komisch zu erklären. Sonst frag nochmal nach.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:38 Uhr.
Seite 1 von 2  1 2      

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