Autor Beitrag
jackie05
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 357



BeitragVerfasst: So 10.01.10 17:21 
Hallo,
ich möchte in Delphi versuchen die Karten zu berechnen wieviel Punkte der Spieler hat.

z.B. auf dem Tisch liegen 5 Karten:
[Bube Schippe] [7 Kreuz] [7 Karo] [4 Schippe] [2 Kreuz]

und die 2 Karten die der Spieler in der Hand hat:
[8 Schippe] [2 Herz]

in dem Fall hat der Spieler 2 Paare und die 2 getroffen.

Wie rechne ich jetzt eigentlich die Punkte zusammen die der Spieler hat?

Ich Spiele erst seit Paar Tagen Poker und weiss noch nicht so richtig wie hoch die Punktzahl bei bestimmten Karten sind, z.B. wieviele Punkte die 2 Paare zusammen gerechnet haben und wieviel Punkte ich bei der 2 bekomme die ich getroffen habe?

Gibt es Vielleicht fertige Unit die das berechnen der Karte vereinfacht?

Oder wie könnte ich das am einfachsten berechnen lassen in Delphi?

Ich bedanke mich schonmal im Voraus.

MfG
Tilman
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: So 10.01.10 17:49 
Du hältst 2 Karten in der Hand, ich nehme also mal an dass wir von "Texas Holdem" sprechen ;) (BTW: Regeln kann man z.B. bei Wikipedia finden).

"Punkte" gibts in Texas Holdem nicht. Was du meinst ist vielleicht der "Rang". Folgende Ränge gibts bei Texas Holdem:

Rang 1 keine Figur
Rang 2 Ein Paar
Rang 3 Zwei Paare
Rang 4 Drilling
usw.

Wenn zwei Spieler ein Paar halten (Rang 2), so gewinnt der Spieler welcher das höchste Paar hält, bzw - sollten beide das selbe Paar halten - der jenige Spieler welcher die höchste Beikarte hält. Und das runter bis zur 5. Karte in er Hand bzw. 3. Beikarte.

//edit
Ich hab mal so ein Programm geschrieben welches unter anderem die Funktionalität enthält zwei Blätter zu vergleichen. Der Source ist aber nicht ganz einfach, und ehrlich gesagt auch nciht besonders schön ^^ (schon ein paar Jährchen her^^).

www.delphi-forum.de/...amp;highlight=prodds

_________________
Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)
Gravitar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 41

Win XP
D6 Ent
BeitragVerfasst: Di 19.01.10 17:15 
user profile iconjackie05 hat folgendes geschrieben Zum zitierten Posting springen:
Hallo,
ich möchte in Delphi versuchen die Karten zu berechnen wieviel Punkte der Spieler hat......


Hi jackie05,

ich habe mir selbst eine Unit geschrieben, die den jeweiligen Rang des Blattes und die Gewinnwahrscheinlichkeit ermittelt.

War übrigens gar nicht so einfach. Ich habe mir die Sourcen von Tilmann angeschaut und fand sie ziemlich kompliziert und auch nicht besonders schön.

Außerdem wollte ich verschiedene Pocket-Hands hinsichtlich der Gewinnwahrscheinlichkeit vergleichen. Also z.B. Ac Kh gegen Qh Jh bei 2 Spielern.

Also flugs selbst ran und losprogrammiert.... im Ergebnis ist mein Source allerdings auch ziemlich kompliziert und nicht sonderlich schön geworden :o .

Das liegt vermutlich daran, dass es nicht so einfach ist, den jeweils höchsten Rang eines Blattes (best 5 of 7) zu ermitteln.

Egal, jetzt funktioniert es. Wenn Interesse besteht, kann ich gern die Unit hochladen.

Gruß, Andreas
JoelH
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 806
Erhaltene Danke: 17

Win10
Delphi Alexandria 11.2 Patch 1
BeitragVerfasst: Mi 20.01.10 09:29 
user profile iconGravitar hat folgendes geschrieben Zum zitierten Posting springen:


Wenn Interesse besteht, kann ich gern die Unit hochladen.


*Hand heb*

Da ich das auch schon mal programmiert habe würde mich dein Code interessieren, vor allem dein Ansatz.

Wieviele Iterationen schafft dein Programm in der Sekunde?

_________________
mfg. Joel
Gravitar
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 41

Win XP
D6 Ent
BeitragVerfasst: Mi 20.01.10 22:24 
Zitat:
user profile iconJoelH
*Hand heb*

Da ich das auch schon mal programmiert habe würde mich dein Code interessieren, vor allem dein Ansatz.

Wieviele Iterationen schafft dein Programm in der Sekunde?


Hi,

na dann wollen wir die Hand nicht verhungern lassen! Unit liegt im Anhang.

Die zentrale Procedure zur Ermittlung des Ranges ist diese hier:

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:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
procedure Rank(var Cards:TPocket);
var
  ranks : array [TRank] of boolean;
  bestcards : array [TRank,0..4of TCards;
  x,y,z,kind,straight_count,n : integer;
  c,flushcolor : TColor;
  straightflag : Tbits;
  rf_flag : boolean;
  r : TRank;
begin
  straightflag := tbits.create;
  straightflag.Size := 15;

  for r := low(TRank) to high(TRank) do
    ranks[r] := false;
  ranks[rkHighCard] := true;

  for x := 0 to 1 do
    myCards[x] := cards.cards[x];

  for x := 2 to 6 do
    myCards[x] := community.cards[x-2];

  kind := 1;
  //myCards absteigend nach Wert sortieren
  //
  for x := 0 to 5 do
    for y := x+1 to 6 do
      if mycards[x].Value < mycards[y].Value then
        swapcards(mycards[x],mycards[y]);
  //prüfen auf Flush
  //
  flushcolor := null;
  c := null;
  repeat
    c := succ(c);
    n := 0; x:= 0;
    repeat
      if  mycards[x].Color = c then
      begin
        bestcards[rkflush,n] := mycards[x];
        inc(n);
      end;
      inc(x);
    until (n > 4or (x > 6);
    if n = 5 then
    begin
      ranks[rkflush] := true;
      flushcolor := c;
    end;
  until (flushcolor > null) or (c = kreuz);

  //prüfen auf straight
  //
  for x := 0 to 6 do
  begin
    straightflag[mycards[x].Value] := true;
    if mycards[x].value = 14 then
      straightflag[1] := true;
  end;
  
  straight_count := 0;
  x := 14;
  repeat
    if straightflag[x] then
    begin
      for y := 0 to 6 do
        if mycards[y].value = x then
          bestcards[rkstraight,straight_count] := mycards[y];
    inc(straight_count)
    end
    else
      straight_count := 0;
    if straight_count = 5 then
      ranks[rkstraight] := true;
    dec(x);
  until (x < 1or ranks[rkstraight];

  //prüfen auf RoyalFlush
  //
  if ranks[rkStraight] and ranks[rkFlush] then
  begin
    straight_count := 0;
    for x := 14 downto 10 do
    begin
      if straightflag[x] then
      begin
        for y := 0 to 6 do
          if (mycards[y].Value = x) and
             (mycards[y].Color = flushcolor) then
          begin
            bestcards[rkRoyalFlush,straight_count] := mycards[y];
            inc(straight_count);
          end;
      end
      else
        straight_count := 0;
    end;
    if straight_count = 5 then
      ranks[rkRoyalFlush] := true;
  end;

  //prüfen auf straightFlush
  //
  if ranks[rkStraight] and ranks[rkFlush] then
  begin
    straight_count := 0;
    for x := 1 to 14 do
    begin
      rf_flag := false;
      if straightflag[x] then
        for y := 0 to 6 do
          if (mycards[y].Value = x) and
             (mycards[y].Color = flushcolor) then
          begin
            rf_flag := true;
            bestcards[rkStraightFlush,straight_count] := mycards[y];
          end;
      if straightflag[x] and rf_flag then
        inc(straight_count)
      else
        straight_count := 0;
      if straight_count = 5 then
      begin
        ranks[rkStraightFlush] := true;
        break;
      end;  
    end;
  end;

  //prüfen auf Set, Pair, DobulePair, FullHouse, 4ofaKind
  //
  for x := 0 to 5 do
  begin
    for y := x+1 to 6 do
      if (myCards[x].Value = myCards[y].Value) and
         (myCards[x].value > 1then
        inc(kind);
    if kind = 4 then
    begin
      ranks[rk4OfaKind] := true;
      n:= 0;
      for y := 0 to 6 do
        if mycards[y].Value = mycards[x].Value then
        begin
          bestcards[rk4OfaKind,n] := mycards[y];
          inc(n);
        end;
      DeletemyCards(myCards[x].value);
      y := 0;
      repeat
        bestcards[rk4OfaKind,4] := mycards[y];
        inc(y);
      until (mycards[y-1].Value > 1or (y > 6);
    end;
    if kind = 3 then
    begin
      ranks[rkSet] := true;
      n := 0;
      for y := 0 to 6 do
        if mycards[y].Value = mycards[x].Value then
        begin
          bestcards[rkSet,n] := mycards[y];
          inc(n);
        end;
      DeletemyCards(myCards[x].value);
      y := 0; n := 0;
      repeat
        if mycards[y].value > 1 then
        begin
          bestcards[rkSet,n+3] := mycards[y];
          inc(n);
        end;
        inc(y);
      until (n = 2or (y > 6);
    end;
    if kind = 2 then
    begin
      y := 0; n:= 0;
      if (ranks[rkPair]) and (not ranks[rkDoublePair]) then
      begin
        ranks[rkDoublePair] := true;
        for y := 0 to 6 do
          if mycards[y].Value = mycards[x].value then
          begin
            bestcards[rkDoublePair,n+2] := mycards[y];
            inc(n);
          end;
        for y := 0 to 1 do
          bestcards[rkDoublePair,y] := bestcards[rkPair,y];
        deletemyCards(myCards[x].value);
        y := 0;
        repeat
          bestcards[rkDoublePair,4] := mycards[y];
          inc(y);
        until (mycards[y-1].Value > 1or (y>6)
      end;
      if (not ranks[rkPair]) and (not ranks[rkDoublePair]) then
      begin
        ranks[rkPair] := true;
        for y := 0 to 6 do
          if mycards[y].Value = mycards[x].value then
          begin
            bestcards[rkPair,n] := mycards[y];
            inc(n);
          end;
        deletemyCards(myCards[x].value);
        y := 0; n := 0;
        repeat
          if mycards[y].value > 1 then
          begin
            bestcards[rkPair,n+2] := mycards[y];
            inc(n);
          end;
          inc(y);
        until (n = 3or (y > 6);
      end;
    end;
    kind := 1;
  end;

  if (ranks[rkSet]) and (ranks[rkPair]) then
  begin
    ranks[rkFullHouse] := true;
    for y := 0 to 2 do
      bestcards[rkFullHouse,y] := bestcards[rkSet,y];
    for y := 3 to 4 do
      bestcards[rkFullHouse,y] := bestcards[rkPair,y-3];
  end;


  //
  //Liefert den höchsten Rang als Resultat zurück
  r := rkRoyalFlush;
  repeat
    if ranks[r] then cards.Rank := r;
    dec(r);
  until ranks[succ(r)];

  //
  //Liefert die 5 besten Karten als Resultat zurück
  for y := 0 to 4 do
    cards.bestfive[y] := bestcards[cards.rank,y];

  straightflag.Free;
end;


Wie gesagt, nicht gerade einfach und sicherlich zu verbessern.

Rekursionen schaffe ich so ca. 380.000 Hände/sek (also austeilen, Flop/Turn/River, Rang ermitteln). Rechner ist ein i7 940, wobei der Quad-Core keine Rolle spielt, da das Ganze nur auf einem Prozessor läuft.

Aus dem Source läßt sich der Ansatz - glaube ich - ganz gut rauslesen.

Gruß, Andreas
Einloggen, um Attachments anzusehen!