Logikproblem bei Spiel

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.
Antworten
Robokopp
User
Beiträge: 64
Registriert: Mittwoch 3. November 2010, 12:04

Hallo

Ich hab ein Quiz gemacht, bei dem man durch richtiges beantworten der Fragen einen Rang aufsteigen kann.
Das mit den Rängen hab ich so gelöst:

Code: Alles auswählen

        if self.score<100:
            self.ui.rang.setText("Spieler: "+str(self.spielername)+"   Rang: Amateur")
        if self.score >200:
            self.rankup()
            self.ui.rang.setText("Spieler: "+str(self.spielername)+"   Rang: Wannabe") 
        if self.score>450:
            self.rankup()
            self.ui.rang.setText("Spieler: "+str(self.spielername)+"   Rang: Wissenshungriger")
        if self.score>750:
            self.rankup()
            self.ui.rang.setText("Spieler: "+str(self.spielername)+"   Rang: Lehrer")
        if self.score>950:
            self.rankup()
            self.ui.rang.setText("Spieler: "+str(self.spielername)+"   Rang: Erhabener")
        if self.score>1200:
            self.rankup()
            self.ui.rang.setText("Spieler: "+str(self.spielername)+"   Rang: Fast Allwissender")
        if self.score>=1500:
            self.rankup()
            self.ui.rang.setText("Spieler: "+str(self.spielername)+"   Rang: Dalai Lama")  

Nun möchte ich bei jedem Rankup einen Sound wiedergeben, weswegen ich in jeder if Schleife self.rankup() aufrufe, die für die Soundwiedergabe zuständig ist.
Leider musste ich feststellen, dass sobald 200 Punkte erreicht sind, bei jeder zusätzlichen richtigen Frage der Sound abgespielt wird, weil ja die Bedingung immer noch erfüllt ist.

Wie könnte ich das lösen?

Eine eindeutige Bedingung mit = kommt nicht in Frage, da man für falsch beantwortete Fragen 5 Punkte abgezogen bekommt und für jede richtige 10 Punkte dazubekommt, wodurch sich auch ungerade Zahlen ergeben.

MfG
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Robokopp hat geschrieben: Nun möchte ich bei jedem Rankup einen Sound wiedergeben, weswegen ich in jeder if Schleife self.rankup() aufrufe, die für die Soundwiedergabe zuständig ist.
If-Schleife

Generell sieht das nach Copy- und Paste-Programmierung aus.

Du solltest Dir Gedanken über eine passende Datenstruktur machen, in der Du jeweils die Schranke und die Bezeichnung für eine Stufe ablegst. Immer wenn Du Punkte dazu gibst (oder abziehst) prüfst Du einfach, ob der neue Punktestand die Schranke des nächsten Ranges übersprungen hat. Nur dann spielst Du einen Sound ab.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
deets

@RoboKopp

Auch wenn Hyperion in allen Punkten Recht hat, ein kleiner Tipp fuer zwischendurch: elif ist das Zauberwort.
Benutzeravatar
snafu
User
Beiträge: 6833
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Bei der Menge an Möglichkeiten würde ich eher zu einem `dict` tendieren. Allerdings steigt damit auch die Komplexität des Codes, weil hier ja mehr als eine standardmäßige "Wert-für-Schlüssel" Abfrage benötigt wird. Müsste man halt abwägen, was einem lieber ist. Wirklich schön ist der Code in seiner jetzigen Form jedenfalls nicht.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Und self.spielername - ist das wirklich kein String, wo es doch mit str() zumindest in einen wandelbar erscheint? Wenn es ein String ist, ist der Aufruf von str() aber so was von überflüssig ...
LivingOn
User
Beiträge: 33
Registriert: Montag 11. August 2008, 07:53

Diese überdimensionalen Fallunterscheidungen lassen sich viel übersichtlicher in einer Tabelle verwalten, z.B. so:

Code: Alles auswählen

import sys

LEVELS = (
    #   von         bis   Status             Sound
    ((    0,        100), "Amateur",         False),
    ((  200,        449), "Wannabe",          True),
    ((  450,        749), "Wissenshungriger", True),
    ((  750,        949), "Lehrer",           True),
    ((  950,       1199), "Erhabener",        True),
    (( 1200,       1499), "Allwissender",     True),
    (( 1500, sys.maxint), "Dalai Lama",       True),
)

def get_status_and_sound(score):
    for (von, bis), status, sound in LEVELS:
        if von <= score <= bis:
            return status, sound

score = 799
status, sound = get_status_and_sound(score)
if sound:
    self.rankup()
self.ui.rang.setText("Spieler: %s   Rang: %s" % (self.spielername, status))
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Also "Tabelle" klingt so nach Assembler :mrgreen: Sagen wir doch hier "Tupel" ;-)

Du hast noch einen "Denkfehler" drin. Man muss sich schon merken, in welchem Status man bisher war. Denn nur bei einem Levelaufstieg soll ja ein Sound gespielt werden bzw. der Status verändert werden und nicht jedes Mal, wenn man Punkte erhält.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
LivingOn
User
Beiträge: 33
Registriert: Montag 11. August 2008, 07:53

Hyperion hat geschrieben:Also "Tabelle" klingt so nach Assembler :mrgreen: Sagen wir doch hier "Tupel" ;-)
Ich habe das Konstrukt als Tabelle bezeichnet, da dieser Begriff "abstrakter" den Sinn beschreibt. Man könnte es auch über Listen implementieren ;-)
Hyperion hat geschrieben: Du hast noch einen "Denkfehler" drin. Man muss sich schon merken, in welchem Status man bisher war. Denn nur bei einem Levelaufstieg soll ja ein Sound gespielt werden bzw. der Status verändert werden und nicht jedes Mal, wenn man Punkte erhält.
Ähm...von meiner Seite her war es nur ein Beispiel wie man dieses überdimensionale if-Konstrukt umgehen kann. Ich wollte keine fertige Lösung präsentieren.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

LivingOn hat geschrieben: Ähm...von meiner Seite her war es nur ein Beispiel wie man dieses überdimensionale if-Konstrukt umgehen kann. Ich wollte keine fertige Lösung präsentieren.
Gut so gesehen... sah mir fast danach aus ;-)

Mir fiel ein, dass ich zu so einem Problem auch mal ein wenig philosophiert hatte: Link
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Robokopp

Welcher Rang erhält der Spieler, wenn seine Punktezahl in den Bereich 100...200 fällt?

Gruß wuf :wink:
Take it easy Mates!
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

@wuf: Das können wir ja dem OP überlassen.

Und was den Aufstiegssound angeht, so kann man das ja auch über den Statusflag regeln. Also, wenn der Flag gegeben ist Sound spielen und fürs nächste Mal auf False setzen. Aber ich würde vielleicht anders kapseln: Nicht alles in eine Datenstruktur und dafür die Überprüfung, ob man einen Rang nach oben geht unabhängig von der Rückgabe des Sounds machen. Der würde dann gespielt, falls es einen Rang nach oben geht. Na ja, letztlich Geschmackssache.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Robokopp

@LivingOn Habe mir erlaubt einige Ideen aus deinem Skript-Snippsel zu übernehmen und etwas in Richtung OOP zusammen zu basteln:

Code: Alles auswählen

import sys

LEVELS =  [
    [0, 100, "Amateur"],
    [200, 499, "Wannabe"],
    [450, 749, "Wissenshungriger"],
    [750, 949, "Lehrer"],
    [950, 1499, "Erhabener"],
    [1200, 1499, "Fast Allwissender"],
    [1500, sys.maxint, "Dalai Lama"]
    ]
    
class Player(object):
    
    def __init__(self, name):
        
        self.name = ''
        self.score = 0
        self.rank = None

class RankScore(object):
    
    def __init__(self):
        
        self.players = dict()
    
    def __call__(self, player, score):
        for rank_level, (min, max, rank_name) in enumerate(LEVELS):
            if min <= score <= max:
                if self.players.has_key(player):
                    rank = self.players[player].rank
                    if rank_level > rank or rank == None:
                        self.players[player].rank = rank_level
                        self.players[player].score = score
                        self.rang_set_text(
                            "Spieler: %s Score: %s  Rang: %s" % (
                                player, score, rank_name))
                        print rank_level
                        self.ring_the_bell()
                else:
                    print "Spieler %s ist noch nicht registriert!" % player
    
    def ring_the_bell(self):
        print "Gong !!!"
    
    def rang_set_text(self, rank_data):
        print rank_data
         
    def add_player(self, player=''):
        if player == '': return
        self.players[player] = Player(player)

if __name__ == '__main__':
    
    rank_scoring = RankScore() 
    rank_scoring.add_player('Coco')         
    
    rank_scoring('Nobody', 1555)
    rank_scoring('Coco', 60)
    rank_scoring('Coco', 150)
    rank_scoring('Coco', 830)
    rank_scoring('Coco', 316)
    rank_scoring('Coco', 1555)
Kann sicher noch optimiert und verbessert werden.

Gruß wuf :wink:
Take it easy Mates!
Robokopp
User
Beiträge: 64
Registriert: Mittwoch 3. November 2010, 12:04

Danke für die nützlichen Antworten, werde mir das alles mal zu Gemüte führen ;)
Antworten