--->Kartenspiel programmieren<----

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.
BlackJack

Beitragvon BlackJack » Dienstag 18. September 2007, 21:24

@Michael Schneider: Der Realität kommt `shuffle()` und `pop()` ohne Index am nächsten, also das was ich vorgeschlagen habe. Nach dem Slicen gibt's die Objekte nicht mehrfach, nur mehr Referenzen darauf. Und natürlich kann man die Slices in der Originalliste auch löschen. Man muss die Realität auch nicht bis ins kleinste Detail nachbilden wenn es einfachere oder zweckmässigere Modellierungen gibt.

@AphrodiTe: `append()` ist eine Methode auf Listen. Hast Du schon das Tutorial in der Python-Dokumentation durchgearbeitet? Das ist für die Grundlagen zu empfehlen.

Und gewöhn Dir bitte die ungarische Notation bei Namen ab. Das ist schrecklich und irreführend wenn man den Typ mal ändern sollte und nicht die Namen anpasst.
Benutzeravatar
Michael Schneider
User
Beiträge: 566
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Beitragvon Michael Schneider » Dienstag 18. September 2007, 22:47

Hallo,

von mir aus kann man auch Shuffle verwenden. Aber wenn ich das hier eingebe:

Code: Alles auswählen

shuffle(lKarten)
print len(lKarten)

Bekomme ich nur eine Liste mit 28 Karten, statt 32. Warum?

Ich habe mal noch eine Funktion geschrieben, die zu jedem Stich die gueltige Werteliste der Karten berechnet. Den Index der Karte innerhalb dieser Liste kann man verwenden, um den Rang der Karte innerhalb des Stiches zu ermitteln. Die Liste respektiert neben der Farbe und dem Wert auch die Art des Spiels (Grand, Null, Farbe) und die ausgespielte Karte:

Code: Alles auswählen

from random import randint

#   Initialisierung
lFarbspiel = ["Ass", "10", "Koenig", "Dame", "9", "8", "7"]
lNullspiel = ["Ass", "Koenig", "Dame", "Bube", "10", "9", "8", "7"]
lFarben = ["Kreuz", "Pik", "Herz", "Karo"]

lKarten = [(sFarbe, sWert) for sWert in lFarbspiel for sFarbe in lFarben]


def draw_card(lKarten):
    if not lKarten:
        return ()
    return lKarten.pop(randint(0, len(lKarten)-1))

def create_order_list(tAusgespielt, sSpiel="Grand"):
    """Erzeugt eine Liste, die die Reihenfolge der Kartenwerte darstellt.

    tAusgespielt - erwartet ein Kartentupel aus (Farbe, Wert)
    sSpiel       - die Spielart: "Grand", "Null", "Kreuz", "Pik", "Herz", "Karo"
    """
    lOrder = []
   
    #   die Karte wird zerlegt in Farbe und Wert
    sAusspielFarbe, sAusspielWert = tAusgespielt

    #   Beim Grand gilt die Wertordnung des Farbspiels, Buben sind Trumpf   
    if sSpiel == "Grand":
        #   Trumpf (Buben) einfuegen
        lOrder.extend([(sFarbe, "Bube") for sFarbe in lFarben])
        #   Farbe der ausgespielten Karte einfuegen
        lOrder.extend([(sAusspielFarbe, sWert) for sWert in lFarbspiel])
        #   Sonstige Karten einfuegen
        lOrder.extend([(sFarbe, sWert) for sFarbe in lFarben
                                           for sWert in lFarbspiel
                                               if not sFarbe==sAusspielFarbe])

    #   Beim Nullspiel reihen sich 10 und Bube ein
    elif sSpiel == "Null":
        #   Farbe der ausgespielten Karte einfuegen
        lOrder.extend([(sAusspielFarbe, sWert) for sWert in lNullspiel])
        #   Sonstige Karten einfuegen
        lOrder.extend([(sFarbe, sWert) for sFarbe in lFarben
                                           for sWert in lNullspiel
                                               if not sFarbe==sAusspielFarbe])

    #   Bei Farbspielen ist 10 > Koenig, Buben sind hoechste Trumpf
    elif sSpiel in lFarben:
        #   Buben einfuegen
        lOrder.extend([(sFarbe, "Bube") for sFarbe in lFarben])
        #   Trumpffarbe (= Spielfarbe) einfuegen
        lOrder.extend([(sSpiel, sWert) for sWert in lFarbspiel])
        #   Farbe der ausgespielten Karte einfuegen, wenn sie nicht Trumpf ist
        if not sSpiel == sAusspielFarbe:
            lOrder.extend([(sAusspielFarbe, sWert) for sWert in lFarbspiel])
        #   Sonstige Karten einfuegen
        lOrder.extend([(sFarbe, sWert) for sFarbe in lFarben
                                           for sWert in lFarbspiel
                                               if not sFarbe in (sAusspielFarbe, sSpiel)])

    else:
        print "Spielart '%s' ist nicht bekannt" % sSpiel
    return lOrder       

#   erzeugt 3 Kartensets a 10 Karten ('Spieler 1', 'Spieler 2', 'Spieler 3') und den Skat
dKartenSets = {}
for iSpieler in xrange(1, 4):
    dKartenSets["Spieler %i" % iSpieler] = [draw_card(lKarten) for i in xrange(10)]
dKartenSets["Skat"] = lKarten

################################################################################
#   Auswertung/Test
print "Deine Hand"
for tKarte in sorted(dKartenSets["Spieler 1"]):
    print "gezogene Karte: %s %s" % tKarte

#   einen Stich zusammenstellen und fuer verschiedene Spiele gegenueberstellen
t1, t2, t3 = ("Karo", "Dame"), ("Karo", "10"), ("Kreuz", "Ass")
lStich = [t1, t2, t3]

print "="*60
print "Karten des Stichs:", lStich
print "%s %s wird ausgespielt" % t1
for sSpiel in ("Grand", "Null", "Karo", "Kreuz", "Pik"):
    print "\nbeim %s:" % sSpiel
    lKartenWert = create_order_list(tAusgespielt=t1, sSpiel=sSpiel)
    print sorted(lStich, key=lKartenWert.index)


Geht aber bestimmt auch einfacher und besser für Anfänger geeignet.

@BlackJack, hast wieder mal recht. Ich dachte Du wärst kategorisch gegens Poppen. ;-)

Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
merlin_emrys
User
Beiträge: 110
Registriert: Freitag 3. März 2006, 09:47

Beitragvon merlin_emrys » Dienstag 18. September 2007, 23:14

Michael Schneider hat geschrieben:Aber wenn ich das hier eingebe:

Code: Alles auswählen

shuffle(lKarten)
print len(lKarten)

Bekomme ich nur eine Liste mit 28 Karten, statt 32. Warum?

Das kann ich nicht reproduzieren; bei mir sind es nach dem shufflen noch immer 32 Karten... Welche fehlen denn? (Bein Pokern würde ich ja zuerst gezielt nachsehen, ob noch alle Asse dasind, aber ich nehme an, das ist beim Skat nicht so relevant...? Andernfalls würde ich mit der KI mal über Mogeln beim Kartenspiel reden wollen :-D ...)
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Beitragvon Rebecca » Mittwoch 19. September 2007, 08:33

Michael Schneider hat geschrieben:Deine Abneigung gegenüber Poppen kann ich nicht nachvollziehen.

Ich auch nicht. :wink:

SCNR
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
BlackJack

Beitragvon BlackJack » Mittwoch 19. September 2007, 08:53

Ich wurde ja auch falsch verstanden. Ich bin nur gegen wildes, zufälliges poppen, anstelle eines effizienten poppens immer schön der Reihe nach, von hinten. :-D
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Beitragvon mkesper » Mittwoch 19. September 2007, 10:30

BlackJack hat geschrieben:Und gewöhn Dir bitte die ungarische Notation bei Namen ab. Das ist schrecklich und irreführend wenn man den Typ mal ändern sollte und nicht die Namen anpasst.

Kommt dieser Unsinn etwa vom Lehrer? Dann sollte ihn schleunigst mal jemand ans Forum oder zumindest an PEP0008 verweisen. :)
AphrodiTe hat geschrieben:Wir haben neulich in der schule mit python angefangen.
AphrodiTe
User
Beiträge: 22
Registriert: Dienstag 18. September 2007, 12:48
Wohnort: Göttingen
Kontaktdaten:

lol

Beitragvon AphrodiTe » Mittwoch 19. September 2007, 14:16

kann ich mit

Code: Alles auswählen

x=["a","b","c"]
if a in x:
    print "a ist in der liste"


fragen ob was in der liste ist??
Die Aussage eines Satzes ist reziprok zur Anzahl der kumulierenden Satzzeichen.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Beitragvon CM » Mittwoch 19. September 2007, 15:14

Probier' es doch einfach aus, aber um einem Mißverständnis vorzubeugen, das aus Deinem Snippet glänzt:

Code: Alles auswählen

>>> l = ['a', 'b', 'c']
>>> a in l
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> 'a' in l
True
>>> x = 'a'
>>> x in l
True


Gruß,
Christian
AphrodiTe
User
Beiträge: 22
Registriert: Dienstag 18. September 2007, 12:48
Wohnort: Göttingen
Kontaktdaten:

sorry

Beitragvon AphrodiTe » Mittwoch 19. September 2007, 16:03

Tut mir leid dass ich es nciht raffe :D aber iwie will es nciht in meinen kopf rein.
ich ahbe eine liste in der 10 karten drinne stehen.
und dann will ich fragen welche karte der benutzer spielen möchte und überprüfen ob die karte in der liste vorhanden ist.

Code: Alles auswählen

karten=["herz 7",...."karo 8"]
x=raw_input("Welche Karte willst du spielen?")

und was kommt dann?
if x in karten = true ???

vielen dank
kai
Die Aussage eines Satzes ist reziprok zur Anzahl der kumulierenden Satzzeichen.
merlin_emrys
User
Beiträge: 110
Registriert: Freitag 3. März 2006, 09:47

Re: sorry

Beitragvon merlin_emrys » Mittwoch 19. September 2007, 16:21

Man könnte es so machen, aber das Problem ist in meinen Augen die Tippfehleranfälligkeit. Python ist da ziemlich "pinibel". Ich würde dem Nutzer daher nur eine Auswahl von 1-10 stellen:

Code: Alles auswählen

# -*- coding: cp1252 -*-
karten = ['herz 7', 'karo 9', 'pik dame']
print "Welche Karte möchtest Du spielen? Bitte gibt ein:"
for karte_nummer in range(1,len(karten)+1):
    print "%i für %s" % (karte_nummer, str(karten[karte_nummer-1]))
Kartennummer = raw_input("Bitte nur die Nummer eingeben: ")


Edit:
"zu_legende_Karte" war oben nicht gut eingesetzt. Es ist
zu_legende_Karte = karten[Kartennummer-1]

Der Term -1 ist wieder nur ästhetischen Kriterien geschuldet - ich bin es gewöhnt, Karten von "1" an zu zählen, eine "Karte 0" finde ich einfach irritierend.
AphrodiTe
User
Beiträge: 22
Registriert: Dienstag 18. September 2007, 12:48
Wohnort: Göttingen
Kontaktdaten:

danke

Beitragvon AphrodiTe » Mittwoch 19. September 2007, 16:29

Vielen dank merlin emrys
und danach setzte ich einfach ein append() befehl ein um die karte aus der eigenen hand zu löschen.
danach wollte ich mit einem split() die karte splitten in wert und farbe.damit der computer bedienen kann und damit man am ende karten vergleichen kann.

melde mich dann eh ncohmal :D

kai
Die Aussage eines Satzes ist reziprok zur Anzahl der kumulierenden Satzzeichen.
merlin_emrys
User
Beiträge: 110
Registriert: Freitag 3. März 2006, 09:47

Re: danke

Beitragvon merlin_emrys » Mittwoch 19. September 2007, 16:42

Noch ein Nachtrag:

"raw_input()" ist immer ein bisschen riskant, wie ich hier im Forum gelernt habe. Daher folgender Vorschlag:

Code: Alles auswählen

# -*- coding: cp1252 -*-
karten = ['herz 7', 'karo 9', 'pik dame']
print "Welche Karte möchtest Du spielen? Bitte gibt ein:"
for karte_nummer in range(1,len(karten)+1):
    print "%i für %s" % (karte_nummer, str(karten[karte_nummer-1]))
while True:
    try:
        Kartennummer=int(raw_input("Nur die Nummer von 1 - %i bitte: " % len(karten) ))
    except ValueError:
        print "Bitte gibt nur eine Nummer im angegebenen Bereich ein!"
    if Kartennummer in range(1,len(karten)+1):
        break   


Zur Erklärung:
while True leitet eine Endlosschleife ein, die nur verlassen wird, wenn das Probramm einem "break" begegnen. Das tut es in diesem Fall erstmal nur, wenn es schafft, aus dem raw_input()-Ergebnis eine Zahl zu machen, denn das ist die Aufgabe von int(). Wenn das nicht hinhaut, wird die Eingabe nicht weiter behandelt - das heißt, auch wenn jemand da Python-Code eingibt, macht das Programm korrekt weiter, indem es sich einfach weigert, mit dieser Eingabe irgendetwas zu machen.
Und dann sorgt die if-Anweisung dafür, daß nicht eine Zahl genommen wird, die außerhalb der Kartenmenge liegt. Erst, wenn alles okay zu sein scheint, wird die Schleife verlassen und das Programm läuft weiter.
BlackJack

Beitragvon BlackJack » Mittwoch 19. September 2007, 17:07

Beide male ist das `range()` ungünstig.

Im ersten Fall ist direktes iterieren über die Karten in Verbindung mit `enumerate()` idiomatischer. Selbst mit `xrange()` würde man beim Angeben der Grenzen 0 und ``len(karten)``, wobei die erste dann wegfallen kann, nur an einer Stelle die Korrektur im 1 machen müssen.

Beim zweiten `range()` wird nur für eine Bereichsüberprüfung eine Liste mit Zahlen erzeugt und in der dann linear gesucht. Das geht auch effizienter/schöner:

Code: Alles auswählen

def main():
    karten = ['herz 7', 'karo 9', 'pik dame']
   
    for i, karte in enumerate(karten):
        print '%d für %s' % (i + 1, karte)
   
    while True:
        try:
            nummer = int(raw_input('Nummer von 1 - %d bitte:' % len(karten)))
            karte = karten[nummer - 1]
            break
        except (ValueError, IndexError):
            print 'Bitte nur eine Nummer im angegebenen Bereich!'
   
    print 'Gewaehlt:', karte


Das ganze liesse sich auch in eine Funktion verpacken, die den Anwender aus einer Liste von Objekten eines auswählen lässt, und wäre damit wiederverwendbar.

Die Modellierung einer Karte als Zeichenkette in der zwei mehr oder weniger unabhängige Informationen, Farbe und Bild/Wert, zusammengefügt sind, ist äusserst ungünstig.
Benutzeravatar
Michael Schneider
User
Beiträge: 566
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Beitragvon Michael Schneider » Mittwoch 19. September 2007, 17:29

BlackJack hat geschrieben:Nach dem Slicen gibt's die Objekte nicht mehrfach, nur mehr Referenzen darauf.

Natürlich Referenzen. "Gibt es mehrfach" meinte ich in dem Sinne, wie es z.B. Baupläne eines Hauses im Kopf und gleichzeitig auf Papier geben kann. Sonst hätte ich geschrieben, dass neue Objekte erzeugt werden.

Gruß,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
AphrodiTe
User
Beiträge: 22
Registriert: Dienstag 18. September 2007, 12:48
Wohnort: Göttingen
Kontaktdaten:

danke blackii

Beitragvon AphrodiTe » Mittwoch 19. September 2007, 17:32

vielen dank,
soll ich die befehle append() und del() in die wile-schleife mit einbauen oder eher anch der schleife schreiben?
wollten die karte die man gelegt hat aus der liste jetzt löschen mit del()
und eine neue liste erstellen mit appand()

vielen dank
kai
Die Aussage eines Satzes ist reziprok zur Anzahl der kumulierenden Satzzeichen.

Wer ist online?

Mitglieder in diesem Forum: __deets__