Skat Spiel - Stiche auswerten

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Joe91
User
Beiträge: 4
Registriert: Montag 20. Dezember 2010, 10:48

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? :)
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

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.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

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.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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. ;)
Joe91
User
Beiträge: 4
Registriert: Montag 20. Dezember 2010, 10:48

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
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@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. :)
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
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.

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")
*edit* ein paar Kommentare hinzu
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

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
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

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.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Joe91
User
Beiträge: 4
Registriert: Montag 20. Dezember 2010, 10:48

@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:

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
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.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

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.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Joe91
User
Beiträge: 4
Registriert: Montag 20. Dezember 2010, 10:48

Xynon1 hat geschrieben:Was ist denn bei dir die Aufspiel Farbe ? - ich nehm mal an das das die zu bekennende Farb ist.
Ja wie der Name eben andeuten sollte - Die Farbe, die aufgespielte wurde :)
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.
Stimmt :) Das gibt Sinn, gute Idee.
Benutzeravatar
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
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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:
Man macht das eigentlich eher so:

Code: Alles auswählen

if karte.farbe in (FARBE_AUFSPIEL, FARBE_TRUMPF):
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@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.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

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.
Habe ich ja geschrieben. Wann braucht 3 (oder 7?) Tabellen. :-)

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
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

noisefloor hat geschrieben:wie machen Schachprogramme das eigentlich?
Warscheinlich mit einer großen Zahl Hashtables, aber ich weiß es leider auch nicht, wäre aber mal interessant.

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. :mrgreen:
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Aber was vergleichst du da eigentlich ?
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.

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
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

:lol:

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.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Antworten