Hey,
Beim Skat gibt es 4 verschiedene Farbspiele, Grand und Null als übliche Spielarten.
Außerdem muss man die Farbe des aufspielenden bekennen.
Ich sitze jetzt vor dem Problem, wie ich aus einer Liste mit 3 Karten am einfachsten ermitteln kann, wer den Stich gewonnen hat. 6 verschiedene Funktionen (für jede Spielart) mit vielen ifs zu schreiben, widerstrebt mir, aber mir fällt im Moment keine Möglichkeit ein, das ganze sinnvoll zu vereinfachen und reduzieren.
Hat von euch vielleicht jemand eine Idee, wie man das angehen könnte?
Skat Spiel - Stiche auswerten
Ich kenne mich mit Skat zu wenig aus, um etwas konkretes sagen zu können, zumal du ja auch keinen Code gezeigt hast, aber grundsätzlich kann es hilfreich sein, die Funktionen an ein Dict zu hängen. Schau dir mal `functools.partial` und `lambda` an. Die Funktion selbst sollte natürlich erst dann ausgeführt werden, wenn der Wert (das Funktionsobjekt) über den Schlüssel geholt wird. Und mit Verlaub, du bist mit Sicherheit nicht der einzige im weiten Web, der ein Skatspiel in Python implementiert hat. Selbst mit der Forensuche hier dürftest du schon einiges finden.
Mein letztes Skatspiel reicht auch weit ins letzte Jahrtausend zurück, aber wenn ich mich recht erinnere, dann unterscheidet sich Grand vom Farbspiel in der Hauptsache (zumindest in der Frage, wer den Stich macht) darin, dass beim Grand nur die Bauern trumpfen (falls das fachsprachlich schwach ist, bitte ich dies zu entschuldigen), insofern könnte man zumindest die 4 Farbspiele und Grand insoweit gemeinsam behandeln, dass z.B. in einer Variablen trumpffarbe die jeweils gespielte Farbe oder eben None (oder sonstwas für Grand) abgelegt wird und bei der Auswertung dies miteinbezogen wird. Das Nullspiel müsste man wohl extra betrachten.
Auf deine Frage nach den "vielen ifs": Ganz ohne würde ich es nicht versuchen, aber evtl. geht es mit weniger ifs als du denkst. Wie snafu schon anmerkte: Ohne Code(auszüge) lässt sich da nicht mehr zu sagen.
Auf deine Frage nach den "vielen ifs": Ganz ohne würde ich es nicht versuchen, aber evtl. geht es mit weniger ifs als du denkst. Wie snafu schon anmerkte: Ohne Code(auszüge) lässt sich da nicht mehr zu sagen.
Ich denke auch das sich das mit einer einzelnen Funktion machen lässt, denn eigentlich brauchen die Karten nur eine Wertung.
Also gib den Karten einen Wert, wie diese interpretiert werden sollen und definiere den Trumpf, dann sollten zwei ifs und eine Funktion reichen.
@numerix: genau genommen im deutschen Blatt "Unter", Bauer ist aber auch eine Möglichkeit.
Und das Nullspiel ist eigentlich auch nichts anderes, die Karten werden nur anders gewertet und Trumpf gibt es keinen.
Also gib den Karten einen Wert, wie diese interpretiert werden sollen und definiere den Trumpf, dann sollten zwei ifs und eine Funktion reichen.
@numerix: genau genommen im deutschen Blatt "Unter", Bauer ist aber auch eine Möglichkeit.
Und das Nullspiel ist eigentlich auch nichts anderes, die Karten werden nur anders gewertet und Trumpf gibt es keinen.
Nochmal ins Blaue geraten: Vielleicht muss es nicht unbedingt einen separaten Bewerter geben. Ich stelle mir das mit dem "Funktionsdict" nämlich nicht gerade schön vor. Man könnte ja auch Klassen machen, die das gemeinsame Verhalten von `Card` erben oder sowas und in ihrer Berechnungsfunktion wissen, mit wieviel Punkten sie bewertet werden. Oder sie tragen ihren Wert schon als Instanzattribut. Oder sie nutzen ein `value`-Property, falls eine dynamische Berechnung nötig ist. Oder die Karten sind eigentlich keine Karten, sondern nur Zahlwerte, die für den User mit einem Namen übersetzt werden. Wie gesagt, ich habe quasi keine Ahnung von dem Spiel, aber vielleicht war ja ein brauchbarer Vorschlag mit dabei.
Hm, also Code zu zeigen würde nichts bringen, da noch so gut wie gar nichts existiert
@Xynon1 und numerix: Ich denke ich versuche es dann mal, indem ich für jedes Spiel jeweils 4 Rangordnungen für die Karten innerhalb der Farbe erstelle. Also eine Liste für Trumpf (Buben + Farbe) und dann für die anderen 3 Farben das selbe, geordnet danach, welche Karte stärker ist.
Danke für die Antworten, vielleicht hab ich das Problem einfach überschätzt
Falls ich bei der Umsetzung Probleme habe, meld ich mich noch mal.
@snafu: Dass man das innerhalb der Card-Klasse macht, halte ich für nicht so praktisch, aber vielleicht liegt das auch daran, dass ich es mir momentan nicht so genau vorstellen kann. Aber es gibt nun mal für jede Spielart eine andere Rangfolge, welche Karte stärker ist und außerdem kommt es auch noch darauf an, welche Karte zuerst aufgespielt wurde.
@Xynon1 und numerix: Ich denke ich versuche es dann mal, indem ich für jedes Spiel jeweils 4 Rangordnungen für die Karten innerhalb der Farbe erstelle. Also eine Liste für Trumpf (Buben + Farbe) und dann für die anderen 3 Farben das selbe, geordnet danach, welche Karte stärker ist.
Danke für die Antworten, vielleicht hab ich das Problem einfach überschätzt
Falls ich bei der Umsetzung Probleme habe, meld ich mich noch mal.
@snafu: Dass man das innerhalb der Card-Klasse macht, halte ich für nicht so praktisch, aber vielleicht liegt das auch daran, dass ich es mir momentan nicht so genau vorstellen kann. Aber es gibt nun mal für jede Spielart eine andere Rangfolge, welche Karte stärker ist und außerdem kommt es auch noch darauf an, welche Karte zuerst aufgespielt wurde.
@snafu
Ok, damit du auch die Regeln kennst fass ich mal schnell das gröbste zusammen.
Es gibt 32 Karten 8 von jeder Farbe, die oben genannten Spielarten sind die Grundarten, also Farb-, Null- oder Grandspiel.
Es gilt, eine generelle Wertung der Karten
Daus(Ass), König, Ober(Dame), Unter(Bube), Zehn, Neun, Acht, Sieben.
Diese gilt aber nur im Nullspiel, in einem Farbspiel ordnen sich die Zehn zwischen Daus und König ein und die Unter sind immer Trumpf, also
Daus(Ass), Zehn, König, Ober(Dame), Neun, Acht, Sieben.
Trumpf gilt gewissermaßen als fünfte Farbe und steht über den anderen.
Nullspiel - es gibt keinen Trumpf es gilt die oben genannte Reihenfolge.
Grand - nur Unter sind Trumpf, in der Reihenfolge Eichel(Kreuz), Blatt/Grün(Pik), Herz/Rot und Schellen(Karo).
Farbspiel - Die gewählte Farbe ist Trumpf
Ich hoffe es ist nicht allzu verwirrend.
Ok, damit du auch die Regeln kennst fass ich mal schnell das gröbste zusammen.
Es gibt 32 Karten 8 von jeder Farbe, die oben genannten Spielarten sind die Grundarten, also Farb-, Null- oder Grandspiel.
Es gilt, eine generelle Wertung der Karten
Daus(Ass), König, Ober(Dame), Unter(Bube), Zehn, Neun, Acht, Sieben.
Diese gilt aber nur im Nullspiel, in einem Farbspiel ordnen sich die Zehn zwischen Daus und König ein und die Unter sind immer Trumpf, also
Daus(Ass), Zehn, König, Ober(Dame), Neun, Acht, Sieben.
Trumpf gilt gewissermaßen als fünfte Farbe und steht über den anderen.
Nullspiel - es gibt keinen Trumpf es gilt die oben genannte Reihenfolge.
Grand - nur Unter sind Trumpf, in der Reihenfolge Eichel(Kreuz), Blatt/Grün(Pik), Herz/Rot und Schellen(Karo).
Farbspiel - Die gewählte Farbe ist Trumpf
Ich hoffe es ist nicht allzu verwirrend.
- Sr4l
- User
- Beiträge: 1091
- Registriert: Donnerstag 28. Dezember 2006, 20:02
- Wohnort: Kassel
- Kontaktdaten:
So könnte man ran gehen. Ist natürlich nicht perfekt. Ich modifiziere die Farben, dadurch ist dann im Beispiel ein pik Bube höher als ein kreuz Bube, aber ich denke der Grundgedanke ist zu erkennen.
*edit* ein paar Kommentare hinzu
Code: Alles auswählen
FARBEN = ["kreuz", "pik", "herz", "karo"]
KARTEN = ["ass", 10, "koenig", "dame", "bube", 9, 8, 7]
BESITZER = [None, "spieler1", "spieler2", "spieler3", "skat"]
class Karte():
"""
kleine Klasse um Kartendaten zu speichern
"""
def __init__(self, farbe, karte, besitzer=None):
self.besitzer = besitzer
self.farbe = farbe
self.karte = karte
def __repr__(self):
return "{0}({1}, {2}, {3})".format(self.__class__.__name__, self.farbe, self.karte, self.besitzer)
def wer_hat_gewonnen(karten, trumpf):
# wir modifizieren die Farben/Karten Liste nach Wertigkeit und je nach Spielmodi (unvollständig)
if trumpf in FARBEN:
FARBEN.remove(trumpf)
FARBEN.insert(0, trumpf)
KARTEN.remove("bube")
KARTEN.insert(0, "bube")
elif trumpf == "grand":
KARTEN.remove("bube")
KARTEN.insert(0, "bube")
elif trumpf == None:
pass
# wir gehen die Karten von stark nach schwach durch, wer davon die erste besitzt hat den sticht gewonnen
for k in KARTEN:
for f in FARBEN:
for i in karten:
if i.farbe == f and i.karte == k:
return i.besitzer
# das sind die gelegten karten
gelegte_karten = [
Karte("kreuz", 10, BESITZER[1]),
Karte("karo", "bube", BESITZER[2]),
Karte("herz", 8, BESITZER[3])
]
print gelegte_karten
print wer_hat_gewonnen(gelegte_karten, "pik")
Da jede Spielvariante eine totale Ordnung auf allen Karten definiert (d.h. jede Karte ist mit jeder Karte vergleichbar und es ist immer eine der beiden besser als die andere) würde ich jede Variante eine passende Sortierfunktion schreiben und dann die Karten danach sortieren und dann einfach den Besitzer der höchsten Karte nachschauen.
Stefan
Stefan
Das meinte ich mit "den Karten einen Wert geben", ob man nun den Wert an der Karte definiert sobald die Spielart gewählt wurde oder das von außen verwaltet wird kommt ja auf das Programm an, wie es aufgebaut ist.
Aber man muss die Reihenfolge noch beachten, da kommt man nicht drumherum.
Aber man muss die Reihenfolge noch beachten, da kommt man nicht drumherum.
@sma: Ja das war mein erster Gedanke, aber wie Xynon1 sagt, man kommt um die Reihenfolge nicht drumherum.
Schließlich muss man ja die Farbe bekennen und wenn man dies nicht tut, kann man den Stich nicht bekommen, außer es handelt sich um Trumpf.
Daher gibt es keine totale Ordnung, zumindest keine, die Unabhängig von der Reihenfolge der gespielten Karten ist, weshalb ich die Idee direkt wieder verworfen habe.
Aber wenn ich noch mal drüber nachdenke, ist das eigentlich nur eine kleine zusätzliche if-Abfrage in dem Stil:
Hört sich eigentlich nach einer guten Idee an und ist auch weniger Arbeit als die vorherige
Ich weiß nur nicht, warum ich selbst nicht darauf gekommen bin, na gut sogesehn bin ich es ja, aber ihr wisst was ich meine.
Schließlich muss man ja die Farbe bekennen und wenn man dies nicht tut, kann man den Stich nicht bekommen, außer es handelt sich um Trumpf.
Daher gibt es keine totale Ordnung, zumindest keine, die Unabhängig von der Reihenfolge der gespielten Karten ist, weshalb ich die Idee direkt wieder verworfen habe.
Aber wenn ich noch mal drüber nachdenke, ist das eigentlich nur eine kleine zusätzliche if-Abfrage in dem Stil:
Code: Alles auswählen
if karte.farbe == aufspielfarbe or karte.farbe == trumpf:
# Karte einen Wert von 1-12 zuweisen - In jeder gibt es die Werte 1-8 und bei der Trumpf-Farbe + 4 für die bauern
else:
# Karte wird nicht berücksichtigt
Ich weiß nur nicht, warum ich selbst nicht darauf gekommen bin, na gut sogesehn bin ich es ja, aber ihr wisst was ich meine.
Was ist denn bei dir die Aufspiel Farbe ? - ich nehm mal an das das die zu bekennende Farb ist.
Soweit sieht es gut aus, aber ich würde die Wertung etwas anders machen, da Trumpf immer über den anderen steht, also würde diese mit 7 anfangen.
Also bei einem Farbspiel: (Karte-Wert)
7-0, 8-1, 9-2, Ober-3, König-4, 10-5, Daus-6, Trumpf7-7, ...
Bei deinem Beispiel, zumindest dem Kommentar zufolge würdest du dann nochmal auf Trumpf prüfen müssen.
Soweit sieht es gut aus, aber ich würde die Wertung etwas anders machen, da Trumpf immer über den anderen steht, also würde diese mit 7 anfangen.
Also bei einem Farbspiel: (Karte-Wert)
7-0, 8-1, 9-2, Ober-3, König-4, 10-5, Daus-6, Trumpf7-7, ...
Bei deinem Beispiel, zumindest dem Kommentar zufolge würdest du dann nochmal auf Trumpf prüfen müssen.
Ja wie der Name eben andeuten sollte - Die Farbe, die aufgespielte wurdeXynon1 hat geschrieben:Was ist denn bei dir die Aufspiel Farbe ? - ich nehm mal an das das die zu bekennende Farb ist.
Stimmt Das gibt Sinn, gute Idee.Xynon1 hat geschrieben:Soweit sieht es gut aus, aber ich würde die Wertung etwas anders machen, da Trumpf immer über den anderen steht, also würde diese mit 7 anfangen.
- noisefloor
- User
- Beiträge: 3856
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
IMHO lässt sich so was auch über statische Tabellen lösen, die jede Spielsituation beschreiben. Man bräuchten dann 3 Tabellen 32x32x32, eine für's Farbspiel (oder eine Tabelle für jedes Farbspiel?), eine für Grand und eine für Null. Über die konkrete Umsetzung habe ich mir aber auch keine Gedanken gemacht. Nachteil: braucht ein bisschen mehr Speicher..
Gruß, noisefloor
IMHO lässt sich so was auch über statische Tabellen lösen, die jede Spielsituation beschreiben. Man bräuchten dann 3 Tabellen 32x32x32, eine für's Farbspiel (oder eine Tabelle für jedes Farbspiel?), eine für Grand und eine für Null. Über die konkrete Umsetzung habe ich mir aber auch keine Gedanken gemacht. Nachteil: braucht ein bisschen mehr Speicher..
Gruß, noisefloor
Man macht das eigentlich eher so:Joe91 hat geschrieben:Aber wenn ich noch mal drüber nachdenke, ist das eigentlich nur eine kleine zusätzliche if-Abfrage in dem Stil:Code: Alles auswählen
if karte.farbe == aufspielfarbe or karte.farbe == trumpf:
Code: Alles auswählen
if karte.farbe in (FARBE_AUFSPIEL, FARBE_TRUMPF):
@noisefloor
Ich bezweifle irgendwie das das Zweckmäßig ist, denn du kannst ja mehrere Spielvarianten haben, wo diese wieder anders ausgewertet werden müssen.
Was zur folge hat, das du nicht nur eine von deinen Matrizen hast sondern so viele wie Spielvarianten existieren.
Da finde ich den bisherigen Ansatz wesentlich besser.
Ich bezweifle irgendwie das das Zweckmäßig ist, denn du kannst ja mehrere Spielvarianten haben, wo diese wieder anders ausgewertet werden müssen.
Was zur folge hat, das du nicht nur eine von deinen Matrizen hast sondern so viele wie Spielvarianten existieren.
Da finde ich den bisherigen Ansatz wesentlich besser.
- noisefloor
- User
- Beiträge: 3856
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Habe ich ja geschrieben. Wann braucht 3 (oder 7?) Tabellen.Xynon1 hat geschrieben:@noisefloor
Ich bezweifle irgendwie das das Zweckmäßig ist, denn du kannst ja mehrere Spielvarianten haben, wo diese wieder anders ausgewertet werden müssen.
Was zur folge hat, das du nicht nur eine von deinen Matrizen hast sondern so viele wie Spielvarianten existieren.
BTW: wie machen Schachprogramme das eigentlich? Da ist die Problemstellung zwar anders (welcher Spielzug macht Sinn?), aber AFAIK arbeiten die auch mit Tabellen, wo alle möglichen Stellungen hinterlegt sind.
Gruß, noisefloor
Warscheinlich mit einer großen Zahl Hashtables, aber ich weiß es leider auch nicht, wäre aber mal interessant.noisefloor hat geschrieben:wie machen Schachprogramme das eigentlich?
Aber was vergleichst du da eigentlich ?
Hier ging es doch um "Stiche auswerten", das ist im Schach doch ganz einfach, wenn eine gegnerische Figur dort steht wo man hinziehen will, ist diese weg.
- noisefloor
- User
- Beiträge: 3856
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
Nach jeder Runde muss man also in die Tabelle gehen, der ausgespielten Karte eine Zahl zuordnen (z.B. Herz 7 = 12) und somit aus den drei Zahl das passende Feld in der Tabelle abfragen, woraus dann hervorgeht, wer den Stich hat.
Gruß, noisefloor
Mein Idee (die, wie gesagt, nur eine Idee ist und nicht wirklich bis ans Ende gedacht) ist, dass man eine 32x32x32 Matrix hat - also für jeden der drei Spieler für jede Karte. Die Felder sind mit einem Wert 1,2 oder 3 belegt; die Zahl sagt, welcher Spieler den Stich bekommt.Aber was vergleichst du da eigentlich ?
Nach jeder Runde muss man also in die Tabelle gehen, der ausgespielten Karte eine Zahl zuordnen (z.B. Herz 7 = 12) und somit aus den drei Zahl das passende Feld in der Tabelle abfragen, woraus dann hervorgeht, wer den Stich hat.
Gruß, noisefloor
Nein, ich meinte deinen Schach-Vergleich.
Du hast die KI eines Schachprogrammes mit "Stiche auswerten" verglichen, welches aber im Schach der Schlagabtausch der Figuren ist.