![]() |
Karten-Verteil-Algorithmus
Guten Mittag
Ich bin gerade dabei, ein kleines Kartenspiel zu programmieren. Dabei sollen je 3 Karten an insgesamt 4 Spieler verteilt werden, also 12 Karten. Das Deck besteht aus 20 Karten. Jede Karte ist nummeriert von 1-20. Nun habe ich mit gedacht, dass ich eine Zufallszahl zwischen 1 und 20 generiere, schaue, ob die in einem Array, welches als Speicher für schon verteile Karten dient, vorhanden ist, wenn ja, dann muss er noch mal eine generieren und schauen, wenn nicht wird sie umgewandelt in den Kartenname und davor noch in das Kartenarray gespeichert. Am Anfang durchgehe ich zwei For-Schleifen, einmal für Spieler 0 bis 3 und dann für Karte 1 bis 3. Allerdings will der Algorithmus noch nicht so richtig, ich bin jetzt seit einer Stunde dran, Fehler zu suchen, aber jedes Mal verteilt er mir die Karten nicht richtig oder läuft in eine Endlosschleife :cry: Wo ist mein bzw. sind meine Fehler?
Delphi-Quellcode:
procedure TSFrame.Mischen();
var i,j,k,zufall:integer; Status:Boolean; Karte,Test:String; begin Randomize; for i:=0 to Length(VerteilteKarten)-1 do VerteilteKarten[i]:=0; for i:=0 to 3 do begin for j:=1 to 3 do begin Status:=false; repeat Status:=false; zufall:=Random(1)+ 20; for k:=0 to Length(VerteilteKarten)-1 do begin if VerteilteKarten[k] = zufall then begin Status:=true; break; end; end; until Status = False; for k:=0 to Length(VerteilteKarten)-1 do begin if VerteilteKarten[k] = 0 then begin VerteilteKarten[k] := zufall; break; end; end; if zufall = 1 then Karte:='K1' else if zufall = 2 then Karte:='E5' else if zufall = 3 then Karte:='H4' else if zufall = 4 then Karte:='H5' else if zufall = 5 then Karte:='K5' else if zufall = 6 then Karte:='P3' else if zufall = 7 then Karte:='P1' else if zufall = 8 then Karte:='P5' else if zufall = 9 then Karte:='P4' else if zufall = 10 then Karte:='E4' else if zufall = 11 then Karte:='E2' else if zufall = 12 then Karte:='H2' else if zufall = 13 then Karte:='K2' else if zufall = 14 then Karte:='H1' else if zufall = 15 then Karte:='K4' else if zufall = 16 then Karte:='P2' else if zufall = 17 then Karte:='E1' else if zufall = 18 then Karte:='E3' else if zufall = 19 then Karte:='H3' else if zufall = 20 then Karte:='K3'; Server.Socket.Connections[i].sendText('-gc'+IntToStr(j)+Karte); TEdit(SFrame.FindComponent('sp'+IntToStr(i+1)+'_k'+IntToStr(j))).Text:=Karte; end; end; end; |
AW: Karten-Verteil-Algorithmus
Mische die Karten nach
![]() |
AW: Karten-Verteil-Algorithmus
Zitat:
Delphi-Quellcode:
for i = 0 to KartenArray.length - 1 do
begin zufall = Random(KartenArray.length - 1); dummy = KartenArray[i]; KartenArray[i] = KartenArray[zufall]; KartenArray[zufall] = dummy; end; |
AW: Karten-Verteil-Algorithmus
Hi,
habe das Thema für mein Poker-Wahrscheinlichkeitsrechner inzwischen sehr performant umgesetzt: 1. Mischen ist nicht notwendig und kostet nur Zeit 2. Lege dir eine Liste vom Typ TCard an (Record Value u. Farbe) 3. Wähle aus der Liste per Zufall eine Karte aus und verteile sie an den Spieler 4. Danach löscht Du diese Karte aus der Liste Dadurch musst du nicht jedesmal prüfen, ob die Karte bereits verteilt wurde. Durch das zufällige Auswählen einer Karte aus der "Kartenliste" sparst du dir auch noch das mischen. |
AW: Karten-Verteil-Algorithmus
Zitat:
Dein Ansatz löscht ein Element aus der Liste. Falls Du nicht gerade eine verkettete Liste verwendest (wobei dann das Auffinden eines Elementes O(n) wäre, also alles andere als performant), wird dein Verfahren bei O(n*n) landen, denn jedes 'Löschen' ist vom Aufwand O(n). Bei meinem bescheidenen Wissen ist O(n) im allgemeinen performanter als O(n*n), zumindest bei vergleichbarem Overhead. Falls ich mich irre, und Du eine Kartenstapel-Klasse/Struktur hast, die dies alles sehr schnell bewerkstelligt, lass es mich wissen. Ich lerne immer wieder gerne dazu. |
AW: Karten-Verteil-Algorithmus
Für die Datenhaltung der Karten gibt es ja zwei Ansätze
* Arrays * Listen Listen sind dabei der abstraktere und bessere Ansatz, denn man braucht nicht darum kümmern, dass beim Löschen einer Karte ein Loch entsteht oder dass beim Einfügen evtl. neuer Platz geschaffen werden müsste. Ein Kartenspiel mit 32 Karten aus dem dann Karten an die Spielerhände verteilt werden lässt sich viel leichter mit Listen als mit Arrays implementieren. Der kleine Overhead, den Listen gegenüber Arrays haben liegt deutlich unter einer Millisekunde - der Spieler bemerkt davon überhaupt nichts. Man benötigt folgende Listen: * Kartengeber (zu Beginn gefüllt mit 32 Karten) * Spieler 1 ... Spieler N * Tisch = Karten die auf dem Tisch liegen Je nach Kartenspiel braucht jeder Spieler noch eine weitere Liste in der er seine gewonnenen Stiche ablegt. Es kann für den Tisch auch zwei Listen geben (verdeckte Karten / offene Karten). Auf jeden Fall sind Listen die Vorraussetzung dafür, dass der Code gut les- und verstehbar wird. Wenn z.B. ein Spieler gewonnen hat und die Karten einsacken will, dann sieht das so aus:
Delphi-Quellcode:
TischList.MoveTo(Sieger.WinList); // alle Karten auf dem Tisch in die "Gewinnliste" verschieben
Da ja ständig Karten zwischen den Listen verschoben werden, sollte die Klasse für die Listen dies speziell berücksichtigen, damit man später mit einem Methodenaufruf auskommt:
Delphi-Quellcode:
AktiverSpieler.HandList.MoveCard(IndexDerKarte, TischList); // gewählte Karte auf den Tisch legen
|
AW: Karten-Verteil-Algorithmus
Bei so einem Code schaudert es mich:
Delphi-Quellcode:
Wie wäre es mit
if zufall = 1 then
Karte:='K1' else if zufall = 2 then Karte:='E5' else if zufall = 3 then Karte:='H4' .... else if zufall = 19 then Karte:='H3' else if zufall = 20 then Karte:='K3';
Delphi-Quellcode:
const kartennamen: array[1..20] of string = ('K1','E5','H4',...,'H3','K3');
.... karte:=Kartennamen[zufall] |
AW: Karten-Verteil-Algorithmus
Zitat:
Das der Spieler davon nix merkt, ist auch klar, aber wenn ich z.B. eine Pokersimulation schreibe, dann macht es sehr wohl einen Unterschied, ob ich pro Sekunde 100000 oder 1000000 Spiele simulieren kann. |
AW: Karten-Verteil-Algorithmus
Zitat:
Delphi-Quellcode:
Abgesehen davon, daß das erste
Status:=false;
repeat Status:=false; zufall:=Random(1)+ 20; ... until Status = False; ... //Orgie mit if Zufall=...
Delphi-Quellcode:
völlig überflüssig ist, nimmt Zufall immer nur den Wert 20 an! Selbst Dein verbesserter Code wird da nichts bringen.
Status:=false;
|
AW: Karten-Verteil-Algorithmus
Naja, das ist natürlich falsch, aber im gegensatz zur IF-Sequenz keine böse Absicht, sondern nur ein Vertipper - richtig wäre und ist wohl auch gemeint
Delphi-Quellcode:
random(20)+1
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:17 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz