überladene operatoren - feste anzahl parameter? [SOLVED]
-
Hiho,
ich bastle gerade an einem Kartenspiel. Es handelt sich um Watten. Das Spiel ist eher unbekannt und wird eigentlich nur an der deutsch-schweizerischen-österreichischen Grenze gespielt. Aber egal.
Um herauszufinden welcher der beiden Spieler einen Stich macht, will ich die 2 Karten(Instanzen der Klasse Karte), die von den Spielern gespielt wurden, miteinander vergleichen.
Hierzu bietet sich es sich ja an den Operator "<" oder ">" zu überladen, da man auch davon spricht, dass eine Karte größer als die andere ist.
Pro Runde wird eine Zahl und eine Farbe von beiden Spieleren "angesagt". Die Karten dieser Farbe und die Karten dieser Zahl "zählen" dann für diese Runde mehr, haben also einen höheren Wert als die anderen.
Das heißt, die Ordnung der Karten ist nicht statisch sondern änderst sich von Runde zu Runde.Wenn ich allerdings versuche einen der obne genannten Operatoren zu überladen, bekomme ich folgende Fehlermeldung:
error: 'bool operator<(Karte, Karte, Karte)' must take exactly two arguments
Mein Funktionsdefinition sieht so aus:
karte.hbool operator<(Karte ka1, Karte ka2, Karte ka3){ }Den 3ten Parameter der Klasse Karte brauche ich um der Funktion die aktuell "angesagte" Zahl + Farbe zu übermitteln (beides schneidet sich ja genau in einer Karte)
Ich habe die Funktion übrigens NICHT IN der Klasse definiert, um das schon mal vorwegzunehmen. Die Funktion befindet sich zwar im gleichen Header aber schön außerhalb der Klasse.
Daher meine Fräge:
Ist die Anzahl der Eingabeparameter bei Operatoren immer fest, in diesem Fall 2??
Und wenn ja, was mach ich dann am Besten? Den Namen der Funktion ändern und die Funtionalität beibehalten?
-
butterbemme schrieb:
Ist die Anzahl der Eingabeparameter bei Operatoren immer fest, in diesem Fall 2??
Ja. Überleg doch mal wie der Aufruf mit 3 Operatoren aussehen soll?
butterbemme schrieb:
Und wenn ja, was mach ich dann am Besten? Den Namen der Funktion ändern und die Funtionalität beibehalten?
Tjoa. Operator < bietet sich hier eigentlich nur bedingt an offen gesagt. Du hast ja wahrscheinlich eine Instanz deines Spiels, die auch die "bevorzugten" Karten kennt. Die bekommt dann halt eine Methode dafür.
-
Yeah, schön das noch jemand on is um die Zeit.
cooky451 schrieb:
butterbemme schrieb:
Ist die Anzahl der Eingabeparameter bei Operatoren immer fest, in diesem Fall 2??
Ja. Überleg doch mal wie der Aufruf mit 3 Operatoren aussehen soll?
Genau so, wie ichs oben schon gepostet hab
. Hätte ja sein können, dass diese Freiheit in C++ zur Verfügung steht.cooky451 schrieb:
butterbemme schrieb:
Und wenn ja, was mach ich dann am Besten? Den Namen der Funktion ändern und die Funtionalität beibehalten?
Tjoa. Operator < bietet sich hier eigentlich nur bedingt an offen gesagt. Du hast ja wahrscheinlich eine Instanz deines Spiels, die auch die "bevorzugten" Karten kennt. Die bekommt dann halt eine Methode dafür.
Okay, das war uch mein nächster Gedanke. Ich hab aber gehofft, dass es mit Operator < geht, da ich bisher noch nie nen Operator überladen hab und mir die Idee hier so elegant vorkam...auf den ersten Blick zumindest...
-
Willst du den operator jedes mal explizit so aufrufen
operator< ( thisCard, thatCard, someCard );oder wie?
Operatoren sind doch dazu gedacht, dass man eine schöne Syntax hinbekommen, wie :
Karte card(100); Karte anotherCard(50); boolean isSmaller = card < anotherCard;und nicht
Karte card(100); Karte anotherCard(50); boolean isSmaller = operator< ( card, anotherCard );Was natürlich auch möglich wäre aber irgendwie nicht Sinn der Sache. Wenn du den Operator so aufrufen willst, dann kannst du dir, wie von cooky schon vorgeschlagen, auch einfach direkt eine eigene Methode mit der gewünschten Funktionalität schreiben. Diese könntest du dann korrekt bennenen und der Aufruf wäre um vielfaches intuitiver als der eines operators.
Mal abgesehen davon, dass operator< ein binärer ist ( was auch nur Sinn mach ) und, wie du schon festgestellt hast, der Aufruf mit 3 Parametern nicht geht.
-
so hab ich das noch garnicht betrachtet. Du hast Recht, der Aufruf wäre wie der einer normalen Funktion und kein Stück einfacher
-
Die Anzahl der Parameter sowie Precedence und Auswertungrichtung der Operatoren in C++ sind fix, d.h. durch Überladung nicht veränderbar.
Und man kann auch keine neuen Operatoren definieren.
-
Du kannst in der class Karte eine static Karte vergleichskarte definieren, die für den Vergleich benutzt wird. Damit brauchst du nur einmal pro Rundenwechsel Karte::vergleichskarte setzen und dein Vergleichsoperator funktioniert.
Es gibt natürlich Probleme wenn du sowas wie std::set<Karte> machst, da das set mit wechselnden Ordnungen nicht klar kommt.
Die bessere Alternative wäre ein Vergleichsobjekt zu bauen.
class Kartenvergleicher{ public: Kartenvergleicher(const Karte &k) : vergleichskarte(k){} bool operator()(const Karte &k1, const Karte &k2){ return irgendwieVergleichen(k1, k2, vergleichskarte); } private: Karte vergleichskarte; }Damit kann man dann std::sort aufrufen.
-
Danke für eure Antworten. Werd mir aus euren Vorschlägen was schönes basteln

-
butterbemme schrieb:
Danke für eure Antworten. Werd mir aus euren Vorschlägen was schönes basteln

Bedenke: die Operatoren > und < können nicht alleine an Hand Ihrer Operanden entscheiden, welche Karte sticht.
1. Watten können mehr als zwei Leute spielen, Du mußt also mehere Karten überprüfen.
2. Das Programm muß auch wissen, welche Karte als erstes gelegt wurde, denn wenn kein Trumpf geworfen wurde, stechen nur Karten der gleichen Farbe (Eichel, Schelle, Gras oder Herz)
3. Wie du schon richtig erkannt hast, wird VOR dem Spiel eine Trumpffarbe bestimmt (und ich glaube auch Zahl, bin mir aber nicht mehr sicher, hab' schon lange kein Watten mehr gespielt)Die Instanz einer Karte alleine kann daher nur entscheiden, ob sie grundsätzlich höher ist wie eine andere. Der kannst Du auch die Regeln für Max, Weli und Spitz mitgeben, da diese immer Trumpf sind. Wenn keiner dieser Trümpfe geschlagen hat, muß die Instanz des Spiels an Hand der Trumpffarbe und Zahl und an Hand der ersten Karte entscheiden, welche Karte gestochen hat.
mfg Martin
-
butterbemme schrieb:
Hiho,
ich bastle gerade an einem Kartenspiel. Es handelt sich um Watten. Das Spiel ist eher unbekannt und wird eigentlich nur an der deutsch-schweizerischen-österreichischen Grenze gespielt. Aber egal.
Um herauszufinden welcher der beiden Spieler einen Stich macht, ...Finde es einen lustigen Zufall, dass wir scheinbar zirka zeitgleich das
selbe Spiel ('Watten') programmieren
Habe jetzt, nach 8 Tagen und ~1800 Zeilen C/WINAPI - Quelltext, mal eine erste,
rudimentäre Version ins Netz gestellt:http://www.free-space.at/silvercoat320/Watten.zip
scheint weitestgehend so zu funktionieren, wie ich es mir vorgenommen hatte.
Der Quelltext ist leider ein Alptraum (hatte Teile davon schon mal
hier im Forum gepostet), ist auch leider nur in 'purem' C und ohne Klassen
oder überladene Operatoren gebastelt worden, deshalb wurde es für einen Troll
gehalten.
Die Funktion, die in meinem Programm berechnet, welcher Spieler sticht,
sieht also z.B. so aus:/* Gibt 0 zurueck, falls der Ausspieler sticht, andernfalls 1 */ static unsigned getCapture(struct tagMove* move){ struct Card *first = GodObject->CardSet + GodObject->Player[move->Ausspieler].Cards[move->AusCardIdx], *second = GodObject->CardSet + GodObject->Player[move->Gegenspieler].Cards[move->GegCardIdx]; if(first->rank != GodObject->valRank){ if(first->color != GodObject->valCol){ if(second->color == GodObject->valCol || second->rank == GodObject->valRank) return 1u; /* 2. Spieler sticht */ else if(first->color != second->color) return 0u; /* 1. Spieler sticht */ else return (first->rank > second->rank) ? 0u : 1u; /* Farbstich */ } else if(second->color != GodObject->valCol) return second->rank != GodObject->valRank ? 0u : 1u; /* Trumpf vs. No-Trumpf */ else{ /* Beide spielten Trumpf */ if(second->rank != GodObject->valRank) return (first->rank > second->rank) ? 0u : 1u; /* Trumpf vs. Trumpf */ else return 1u; /* 'Die Rechte' sticht immer. */ } } if(second->color != GodObject->valCol || second->rank != GodObject->valRank) return 0u; /* Falls zuerst Schlag gespielt wurde, sticht der 1.Spieler, ausser ...*/ return 1u; /* ... der 2. Spieler spielt 'die Rechte' */ }Ist nämlich gar nicht so trivial, speziell in Fällen, wo der 2. Ausspieler
die falsche Farbe draufspielt usw.
Sinngemäß so ähnlich wie diese Funktion
(hab mich bemüht, sie gründlich zu kommentieren!) würde man wohl auch in
C++ irgendwelche Operatoren überladen (hab allerdings NULL Ahnung von C++),
die herausfinden sollen, ob die zuerst oder die als zweites gespielte Karte
sticht.
Im Nachhinein betrachtet war's für mich persönlich eine sehr gute Übung,
das Projekt war weder zu klein, noch zu groß, also gerade richtig, um
sich allmählich beim Programmieren zu verbesseren (immer einen Schritt
nach dem anderen machen, und erst wenn ich mal 'sehr' gut in C bin, trau ich
mich auch mal an das viel umfangreichere und kompliziertere C++ ran, bis dahin -> C)Viel Erfolg auch mit Deinem eigenen WATTEN, vielleicht kannst ja auch mal
einen Link zu einer 'spielbaren' (muss noch nicht fertig sein!)
Version posten
Liebe Grüße