--->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.
merlin_emrys
User
Beiträge: 110
Registriert: Freitag 3. März 2006, 09:47

Mittwoch 19. September 2007, 18:00

AphrodiTe hat geschrieben:vielen dank,
soll ich die befehle append() und del() in die wile-schleife mit einbauen oder eher anch der schleife schreiben?
Es geht beides. Ich würde es eher nach der Schleife machen, aber ich kann nicht genau erklären, warum eigentlich.
AphrodiTe
User
Beiträge: 22
Registriert: Dienstag 18. September 2007, 12:48
Wohnort: Göttingen
Kontaktdaten:

Mittwoch 19. September 2007, 18:05

ja ich ahbe es jertzt anch der Schleife eingebaut..

Code: Alles auswählen

del Deine_Karten[nummer-1]
print Deine_Karten
das funktioniert super.
nur wenn ich angeben will dass er in eine neue liste die karte reinschreiben soll macht er es nciht.
habe mir das gedacht:

Code: Alles auswählen

stich.append(Deine_Karten[nummer-1])
stich ist die neue liste die ich vorher schon erstellt ahbe

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

Mittwoch 19. September 2007, 18:24

Was kommt denn für eine Fehlermeldung?
Ich habe die beiden Befehle jetzt mal in meine letzte Schleifenversion eingebaut (habe keine Lust, sie umzutexten... :-( ), und da scheint es zu funktionieren:

Code: Alles auswählen

# -*- coding: cp1252 -*-
karten = ['herz 7', 'karo 9', 'pik dame']
stich = []
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):
        print "Gewählt wurde: ", karten[Kartennummer-1]
        stich.append(karten[Kartennummer-1])
        del karten[Kartennummer-1]
        break    
print stich
print karten
Dann bekomme ich:

Code: Alles auswählen

>>> 
Welche Karte möchtest Du spielen? Bitte gibt ein:
1 für herz 7
2 für karo 9
3 für pik dame
Nur die Nummer von 1 - 3 bitte: 2
Gewählt wurde:  karo 9
['karo 9']
['herz 7', 'pik dame']
Edit:
Noch eine Frage an BlackJack: Du hast geschrieben, meine zweite range()-Anwendung sei ungünstig. Ich habe jetzt doch mal meinen Code umgetextet, weil ich mir ein bestimmtes Phänomen nicht erklären konnte. Aber wenn ich die range()-Funktion weglasse, bricht das Programm bei einer zu hohen Zahleneingabe mit einer Fehlermeldung ab, was ich als eher störend empfinde. Jetzt bin ich verwirrt... Wie könnte man falsche Zahleneingaben noch "abfangen"?

(Das erwähnte Phänomen ist leider nicht reproduzierbar: Als ich bei ein paar Testläufen nur die Eingabetaste gedrückt habe, wurde immer zunächst die Meldung "Bitte gibt nur ...." angezeigt und dann der Auswahltext wieder angezeigt, aber sofort (d.h. ohne weitere Eingabe von mir) die Karte 'pik dame' ausgewählt. Jetzt passiert es nicht mehr... Weiß irgendwer, was da los war? Ich verwende zum Testen python 2.4 mit IDLE.)
Zuletzt geändert von merlin_emrys am Mittwoch 19. September 2007, 18:40, insgesamt 2-mal geändert.
schlangenbeschwörer
User
Beiträge: 419
Registriert: Sonntag 3. September 2006, 15:11
Wohnort: in den weiten von NRW
Kontaktdaten:

Mittwoch 19. September 2007, 18:34

Was passiert denn? Gibts ne Fehlermeldung?
AphrodiTe
User
Beiträge: 22
Registriert: Dienstag 18. September 2007, 12:48
Wohnort: Göttingen
Kontaktdaten:

Mittwoch 19. September 2007, 19:26

hi merlin emrys,
das prob hatte ich auch als ich es ohne die def main(): kopiert habe...alle tabs müssen stimmen...
hab es dann ncoh hinbekommen...


hoffe es geht danach
kai
Die Aussage eines Satzes ist reziprok zur Anzahl der kumulierenden Satzzeichen.
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Mittwoch 19. September 2007, 19:40

Hallo!
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.
Offenbar hat er die von mir abgeschaut. Die Idee habe ich ohne speziellen Namen aus einem alten Programmierbuch abgeschaut und sie hat sich bislang als sehr nützlich erwiesen.

Was meine Verständnislosigkeit angeht, so hat diese inzwischen ein globales Maximum erreicht. Warum scheint hier jeder gegen die Konvention zu sein, den Typ einer Referenz im Namen kenntlich zu machen (was ja laut Wikipedia.de auch gar nicht die ursprüngliche Ungarische Notation ist)?

1.) Ich habe in Pep 8 nur diese Passage gefunden:
Pep 8 - Style Guide hat geschrieben:In Python,
this style is generally deemed unnecessary because attribute and method
names are prefixed with an object, and function names are prefixed with a
module name.
Sie ist also bekannt und es wird nicht davon abgeraten, sie zu verwenden.

2.) Wenn man eine Variable MyButton hat und sie nach einer Änderung nur noch einen Index enthält, dann müsste man diesen Namen auch ändern.

3.) Wenn man neuen Code das erste mal liest, ist diese Hilfe zweifellos Gold wert. Sieht man irgendwo

Code: Alles auswählen

Namen.keys()
dann kann man daraus allein nicht sehen, dass wahrscheinlich ein Fehler vorliegt. Heißt es aber

Code: Alles auswählen

lNamen.keys()
sieht man schon beim Überfliegen, dass hier eine Dictionary-Methode auf eine Liste angewendet wird.

Im Sinne einer freien Meinungsbildung bitte ich höflichst um eine sachliche Diskussion - vielleicht auch in einem neuen Thread, wenn ihn jemand öffnen könnte.

Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
BlackJack

Mittwoch 19. September 2007, 20:17

@merlin_emrys: (Bessere) Alternative zur Bereichsüberprüfung:

Code: Alles auswählen

if x in range(a, b): pass

# =>

if a <= x < b: pass
Gehen wir mal von x=50, a=0 und b=100 aus, dann wird im ersten Fall eine Liste mit 100 Zahlen erzeugt und dann folgen 50 Vergleiche bis klar ist, dass `x` im Bereich ist. Für `x`\e die nicht im Bereich sind, werden immer 100 Vergleiche gemacht. Beim zweiten Fall sind es immer nur zwei Vergleiche und es wird nicht jedesmal eine Liste erzeugt und nach dem Test wieder verworfen.

@Michael Schneider: Den Typ in einer dynamischen Sprache im Namen zu kodieren ist einfach irreführend und läuft dem "duck typing" zuwieder.

zu 2) Damit hast Du ein komplett anderes Objekt und damit auch die Bedeutung verändert. Das sollte sich natürlich auch im Namen wiederspiegeln.

zu 3) Das eine nicht vorhandene Methode aufgerufen wird, kann man nur zur Laufzeit feststellen, egal wie der Name aussieht. Das findet man durch Tests, die man sowieso machen muss, weil kein Name garantiert das bei `lNamen` *wirklich* eine Liste an den Namen gebunden ist. Desweiteren will man das in der Regel auch gar nicht so festlegen. An `lKarten` kann man eine Liste binden. Wenn gar nicht die ganze `list()`-API benötigt wird, kann es aber günstiger sein ein Tupel, ein `set()` oder vielleicht ein Objekt vom Typ `Talon` oder `Hand` zu binden ohne das sich am Programm etwas ändert. Nur ist der Name `lKarten` dann "falsch", also irreführend.

Was Du da so ein bisschen über Namenskonvention einführen willst, ist statische Typinformation. Mit den gleichen Argumenten wollen ja immer wieder Leute Python zu Java machen. "Aber dann kann man ja schon vorher Typfehler erkennen"…
AphrodiTe
User
Beiträge: 22
Registriert: Dienstag 18. September 2007, 12:48
Wohnort: Göttingen
Kontaktdaten:

Mittwoch 19. September 2007, 20:28

hallo allerseits,
ich wollte mit karte.split() eine karte splitten...z.b. aus herz 7 wird [herz, 7]
danach kann ich ja mit if karte[0]=herz nachgucken ob die karte herz oder pik oder kreuz oder karo ist.
wenn jetzt klar ist dass die karte herz ist soll python bei dem gegner 1 in der kartenliste nachgucken und endscheiden ob er auch herz hat.
wie kann ich das machen.
hier mien programm bisher:

Code: Alles auswählen

from random import randint


def draw_card(lKarten):
    if not lKarten:
        return ()
    return lKarten.pop(randint(0, len(lKarten)-1))
   
lFarben = ["Kreuz", "Pik", "Herz", "Karo"]
lWerte = ["7", "8", "9", "10", "Bube", "Dame", "Koenig", "Ass"]
lKarten = [(sFarbe, sWert) for sWert in lWerte for sFarbe in lFarben]

print "Deine Karten"
Deine_Karten = []    
for i in xrange(10):
    got_card = draw_card(lKarten)   
    Deine_Karten.append(got_card)

Gegner1_Karten = []    
for i in xrange(10):
    got_card = draw_card(lKarten)   
    Gegner1_Karten.append(got_card)

Gegner2_Karten = []    
for i in xrange(10):
    got_card = draw_card(lKarten)   
    Gegner2_Karten.append(got_card)



def Anfang():
    stich=[]
    for i, karte in enumerate(Deine_Karten):
            print '%d für %s' % (i + 1, karte)
       
    while True:
        try:
            nummer = int(raw_input('Welche Karte möchtest du spielen?Nummer von 1 - %d bitte:' % len(Deine_Karten)))
            karte = Deine_Karten[nummer - 1]
            break
        except (ValueError, IndexError):
            print 'Bitte nur eine Nummer im angegebenen Bereich!'
       
    print 'Gewaehlt:', karte
del Deine_Karten[nummer-1]
stich.append(Deine_Karten[nummer-1])
print stich
print Deine_Karten
karte=karte.split()

    



Anfang()
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

Mittwoch 19. September 2007, 21:39

AphrodiTe hat geschrieben: wenn jetzt klar ist dass die karte herz ist soll python bei dem gegner 1 in der kartenliste nachgucken und endscheiden ob er auch herz hat.
wie kann ich das machen.
mit der Verbindung 'if ... in ...' kann man nur nach ganzen Listenelementen suchen. Insofern muß man die Listenelemente vermutlich einzeln durchgehen. Ich habe mich mal wieder bei einer Codeformulierung von BlackJack bedient:

Code: Alles auswählen

gesuchtes_Symbol = 'herz'
for i, karte in enumerate(karten): 
    if gesuchtes_Symbol in karten[i]:
        print "Karte %s hat das richtige Symbol." % karten[i]
Die Alternative wäre, von der Zuordnung der Karten als Tupel wegzugehen und sich etwas anderes auszudenken, was ein einfacheres Suchen ermöglicht... Allerdings bin ich mir da selbst nicht so sicher, was da wohl geschickt wäre.

@ BlackJack: Danke! Wird sofort in meinen Programmen entsprechend geändert...
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Mittwoch 19. September 2007, 21:40

Hallo!

Ich habe meine Antwort auf BlackJack bezüglich Typinformationen im Namen verlegt in Thread: "Typinformation im sNamen - Pro/Contra"
http://www.python-forum.de/topic-12025.html

Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Mittwoch 19. September 2007, 22:21

Hallo AphrodiTe,

wie wäre es mal wieder mit einer Listenlösung?

Code: Alles auswählen

from random import shuffle
lFarbspiel = ["Ass", "10", "Koenig", "Dame", "9", "8", "7"]
lNullspiel = ["Ass", "Koenig", "Dame", "Bube", "10", "9", "8", "7"]
lFarben = ["Kreuz", "Pik", "Herz", "Karo"]

#   erzeuge je eine Liste mit allen Karten einer Farbe -> Nullspiel
#   -> Listen ohne Buben fuer Grand und Farbspiele moeglich
dKartenSet = {}
for sFarbe in lFarben:
    dKartenSet[sFarbe] = [(sFarbe, sWert) for sWert in lNullspiel]

#   Kartendeck erzeugen und durchmischen
lKarten = [(sFarbe, sWert) for sWert in lNullspiel for sFarbe in lFarben]
shuffle(lKarten)

#   10 Karten auf Hand nehmen
lHand = lKarten[:10]

### Auswertung #####################################################

#   Handkarten anzeigen
print "#"*80
print "Karten auf der Hand:"
for tKarte in sorted(lHand):
    print "%s %s  " % tKarte,
print "\n"

for sFarbe in lFarben:
    print "Karten der Farbe %s auf der Hand:" % sFarbe,
    print filter(lambda t: t in dKartenSet[sFarbe], lHand)
    print
Zum Lösungsansatz:
Ich habe vier Listen erzeugt, die jeweils alle Kartentupel einer Farbe enthalten. Die kann man jetzt nur für Null nehmen, man kann aber auch Listen ohne die Buben anfertigen und für Farb- und Grandspiele nehmen.

filter ist eine eingebaute Funktion, der man zwei Parameter übergibt. Der Erste ist eine Funktion (in diesem Fall eine mit Lambda schnelldefinierte Funktion, die prüft, ob das übergebene Kartentupel in der gewünschten Farbliste ist), der Zweite ist eine Sequenz (oder iterierbares Objekt), deren Elemente in einer Schleife an die Funktion (Parameter 1) übergeben wird. Ergebnis ist eine Liste aller Elemente des zweiten Parameters, für die die Funktion den Wahrheitswert True ergab.

Praktisch bedeutet das, dass Du genau die Karten einer Hand in einer Liste erhältst, die die entsprechende Farbe haben. Wenn Du aus jeder Hand eine Karte ausgewählt hast, kannst Du mit meiner weiter oben vorgestellten Funktion bequem die höchstwertige davon ermitteln.

Grüße,
Michael
Gruß,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Vingdoloras
User
Beiträge: 53
Registriert: Sonntag 2. Dezember 2007, 18:25

Sonntag 2. Dezember 2007, 20:26

also erstmal...
ich hab hier häufig gesehn, dass ihr, um Zahlen einzulesen

Code: Alles auswählen

int(raw_input())
benutzt... mein Lehrer hat mir gesagt, dass das dasselbe ist wie

Code: Alles auswählen

input()
was zwar nur ein paar Zeichen spart, aber Fehler vorbeugt,
denn man kann sehr schnell eine Klammer vergessen.
z.B.

Code: Alles auswählen

int(raw_input("Gib eine Zahl ein!")
Ich wollte auch ein Skat Prog schreiben, mein Vater hat mich davon abgebracht, denn die KI zu Programmieren wäre wirklich zu hoch...
aber sowas, wie du es willst, wäre für den Anfang machbar.

Nun weiß ich nicht, was ihr im Unterricht macht. Du sagst zum Beispiel, du kennst nur ein paar Grundfunktionen oder so, aber nutzt schon Listen. Ich weiß zwar nicht, warum, aber wir haben mit Listen erst vor kurzem angefangen.
Ich würde dir das Buch "Python 2.x" empfehlen, wenn du 2.4 mit ILDE nutzt, ich habs durchgelesen, als Anfänger versteht man zwar nicht alles auf anhieb, aber ich könnte jetzt mit den Zehntklässlern meiner Schule mithalten (ich bin Neuntklässler und hab dieses Schuljahr mit Python angefangen) zumindest, was die Theorie angeht.

Oder schau dir mal das an:
http://abop-german.berlios.de/

...

nun zum eigentlichen Thema wieder^^
man könnte doch ne Klasse "kartenstapel" und ne Klasse "Hand" erstellen, die man so definiert, dass bei "stapel minus hand" der Hand eine bestimmte menge Karten zugewiesen wird und bei
"stapel mal irgendwas" der stapel gemischt wird zum beispiel... dass würde alles in getrennte Abschnitte teilen, die leichter zu lösen wären.
Allerdings weiß ich nicht, wie es sich mit dem Skat verhält, da ich die Regeln noch nicht so gut kenne...
Zuletzt geändert von Vingdoloras am Montag 3. Dezember 2007, 14:25, insgesamt 1-mal geändert.
Vingdoloras
User
Beiträge: 53
Registriert: Sonntag 2. Dezember 2007, 18:25

Sonntag 2. Dezember 2007, 21:00

ich hoffe der thread is überhaupt noch aktiv :roll:
ich weiß nich ob das klappt, probierts mal aus

Code: Alles auswählen

from random import randint

class Kartenstapel:
    def __init__(self):
        self.inhalt=["Karo 7","Karo 8","Karo 9","Karo 10",
                     "Karo Bube","Karo Dame","Karo Koenig",
                     "Karo Ass","Herz 7","Herz 8","Herz 9",
                     "Herz 10","Herz Bube","Herz Dame",
                     "Herz Koenig","Herz Ass","Pik 7","Pik 8",
                     "Pik 9","Pik 10","Pik Bube","Pik Dame",
                     "Pik Koenig","Pik Ass","Kreuz 7","Kreuz 8",
                     "Kreuz 9","Kreuz 10","Kreuz Bube","Kreuz Dame",
                     "Kreuz Koenig","Kreuz Ass",]
        # Die Liste mit den Karten, mehr wird für den Stapel ja nicht gebraucht
    def __sub__(self,other): # nur für die Verwendung mit der Später
        # erstellten Klasse "Hand" nützlich
        karte=self.inhalt.pop(randint(0,len(self.inhalt)-1))
        other+karte # other darf nur aus Klasse "Hand" instanziert sein

class Hand:
    def __init__(self):
        self.inhalt=[]
        # anfangs leer
    def __add__(self,other):
        self.inhalt.append(other)
        print "Sie haben %s gezogen."%other
dann halt einfach eingeben

Code: Alles auswählen

stapel=Kartenstapel()
hand=Hand()
stapel-hand
Zuletzt geändert von Vingdoloras am Montag 3. Dezember 2007, 15:56, insgesamt 3-mal geändert.
BlackJack

Sonntag 2. Dezember 2007, 22:09

`input()` führt beliebigen Python-Quelltext aus, darum sollte man das nicht verwenden. Ausserdem können da bei Falscheingaben genau so Fehler entstehen wie bei `raw_input()`, d.h. für ein robustes Programm muss man sowieso eine Fehlerbehandlung vorsehen.

Die Operatoren auf diese Weise zu überschreiben ist keine gute Idee. Das macht das Programm nur unverständlich weil niemand auf Anhieb weiss was ``stapel - hand`` bedeuten soll. Ich hätte zum Beispiel spontan darauf getippt, dass ein neuer Kartenstapel erzeugt wird, der alle Karten von `stapel` enthält ausser denen die in `hand` auch vorhanden sind. Eben was man beim "abziehen" so erwarten würde. Und dann würde ich mich wundern warum das Ergebnis an keinen Namen gebunden wird.

Klassennamen werden per Konvention übrigens in "MixedCase" geschrieben, also `Kartenspiel` und `Hand`.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 3. Dezember 2007, 00:08

Vingdoloras hat geschrieben:also erstmal...
ich hab hier häufig gesehn, dass ihr, um Zahlen einzulesen

Code: Alles auswählen

int(raw_input())
benutzt... mein Lehrer hat mir gesagt, dass das dasselbe ist wie

Code: Alles auswählen

input()
Das stimmt so nicht. Wenn du unter `help(input)` nachschlägst kannst du dort lesen, dass es `eval(raw_input())` entspricht. Das ist nicht das gleiche, denn damit kannst du beliebigen Code ausführen und du kannst dir nicht sicher sein, dass das was eingetippt wurde eine Zahl ist. Kann alles mögliche sein und wenn du darauf zugreifst und es keine Zahl ist dann knallts später an irgendeiner Stelle.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Antworten