Textadv "FinalF"

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Du hast zwei "clear"-Funktionen. Einmal main.clear() und dialog.cls(). Da wäre auch ein Modul mit allen diesen Werkzeugen, die du in mehreren Modulen brauchst, sinnvoll.
Ansonsten schreibt man Konstanten normalerweise GROSS. Gibt auch ein paar Tippfehler im Code. So heißt es "successful" und "wrapped", nicht "successfull" und "wraped".
dialog.msg()
Auch hast du in dialog.msg (warum abgekürzt? message ist besser, und bedeutet mit Code-Completion sogar gefühlt kürzer) in allen Zweigen der if-Abfrage als erstes "box_width = 50".
Typen vergleicht man mit "is_instance":

Code: Alles auswählen

>>> is_instance("foo", str) # besser als  type("foo") == str
True
...

Code: Alles auswählen

elif type(obj) == tuple or list:
:shock: Die Zeile liefert immer True!!!! Sie wird nämlich so ausgewertet:

Code: Alles auswählen

elif (type(obj) == tuple) or (list):
Und da "list" immer True ist, ... Zudem wiederholst du den Code:

Code: Alles auswählen

                    for string in wraped_text:
                        print("{0} {1}".format(box_symbol_side, string))
dialog.line()
Das fänd' ich schöner:

Code: Alles auswählen

print({"small": ...,
       "normal": ...,
       ...}[argument])
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Immer noch vieles Unschönes drin.

Zum Beispiel in `main.py` neben der schon erwähnten schlechten Namensvergabe fällt mir noch auf, dass du `print()` anscheinend nicht richtig verstanden hast. Aus dem ``print("{0} {1}".format(self.mID, self.mlabel))`` in `Menu.print_menu_entry()` lässt sich nämlich viel einfacher ein ``print(self.mID, self.mlabel)`` machen. Die `print`-Funktion sorgt da schon selbst für die nötigen Leerzeichen zwischen den Argumenten, da es die Default-Einstellung für den Trenner ist. Nebenbei ist auch dies ein schlechter Name, denn eine Methode der `Menu`-Klasse muss nicht nochmal erwähnen, dass sie sich auf das Menü bezieht. Hier würde `Menu.print_entry()` besser klingen. Abgesehen davon ist es ja - wie auch schon gesagt wurde - eher ein `MenuEntry`. Und im Grunde ist überhaupt keine `.print()`-Methode nötig. Du könntest besser `__str__()` implementieren und dort die von dir genutzte Formatierung als String zurückliefern. Ein Benutzer der Klasse kann dann (mehr oder weniger implizit) auf die String-Repräsentation zurückgreifen, wenn er die Menüeinträge anzeigen will. Ich denke da an eine `Menu`-Klasse, die eine Liste von `MenuEntry`s als Instanzattribut beherbergt und zum "Rendern" ein ``'\n'.join(self.entries)`` benutzt. Das ist aber wahrscheinlich alles noch ein bißchen zu hoch für dich und von daher sei dir verziehen. ;)

`Menu.is_main()` und `Menu.is_battle()` sind auch nicht schön. Du brauchst dort keinen expliziten Wahrheitswert anzugeben. Es würde reichen, jeweils ``return self.mtype == 'main'`` bzw ``return self.mtype == 'battle'`` anzugeben.

Das mit der `mID` ist viel zu undurchsichtig. Hier solltest du besser Konstanten definieren.

So, und jetzt hab ich keine Lust mehr, zu nörgeln und geh ins Bett... :)
Benutzeravatar
kevind
User
Beiträge: 71
Registriert: Montag 22. Oktober 2012, 20:23
Wohnort: /dev/null

Oh mann da denkt man jedesmal "jetzt ist es uper" aber dann wird hier einem schnell wieder die Augen geöffnet ;)

Was versteht ihr genau unter Konstanten ? Ich kenne den "variablen typ" konstante, oder eine konstante in form von "123" zb. Wie soll ich das in verbindung mit mID bringen ?
nomnom hat geschrieben:...Und die Vermischung von dem, was außerhalb der Klasse definiert wird, und dem, was innerhalb der Klasse steht, finde ich auch unsauber...
Meinst du das ich auf Methoden von "Game" innerhalb des Menüs zugreiffe ?

Mir ist auch aufgefallen das es eigentlich kein Menü ist... Die einzelnen Instanzen der Klasse Menü sind eigentlich wie erwähnt Menü Einträge wobei jeder Eintrag alle Funktionen des ganzen "Menüs" enthält. Finde ich nicht so schön. Mir ist bisher leider kein besserer Weg eingefallen. (Für Ideen bin ich offen :))

@snafu

Naja ich verwende "print" hab es aber nicht studiert... der Grund warum ich print mit {} vewendet habe ist damit alle print gleich sind. (Zugegeben sind meine Ideen auch nicht immer die besten ;))

Bzgl. der Menü Klasse mit den Entrys, meinst du dass beim erstellen eines "MenüEntrys" sich dieser automatisch in ein "Menü Klassenobjekt" hinzufügt ?

Danke für deine aufbauenden Worte :roll:
Zuletzt geändert von kevind am Freitag 19. April 2013, 08:02, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo kevind,

Deine neue »Attribute«-Klasse enthält lauter Getter die völlig unnötig sind. In Python greift man direkt auf Attribute zu und benutzt im Gegenteil Properties, falls sich doch noch mehr dahinter versteckt.

»vitality« und »max_vitality« scheinen mir eine einziges Attribut mit Maximal-Wert zu sein. Dieses besondere Verhalten solltest Du nicht in Deiner Character-Klasse abbilden sondern dafür eine neue Attributklasse erzeugen.

In CreateGame.damage_calc gibt es den Zweig »not npc«, »npc« und was soll dann noch das dritte sein?
Benutzeravatar
kevind
User
Beiträge: 71
Registriert: Montag 22. Oktober 2012, 20:23
Wohnort: /dev/null

Hey Sirius3,

du meinst hier "name, value, ID" ?

Wie ich das mit Vitality noch anders lösen könnte werde ich überlegen.

Ja du hast recht das ist quatsch. Da würde eigentlich "if, else" reichen.

Danke soweit !
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@kevind: ja genau
Dann wird »Attribute« einfach:

Code: Alles auswählen

class Attribute():
    def __init__(self, atr_value, atr_name):
        self.value = atr_value
        self.name = atr_name

    def reduce(self, amount=5):
        self.value -= amount

    def improve(self, amount=5):
        self.value += amount

    def improve_for_newround(self):
        self.value += random_value() + random_value()

    def __str__(self):
        return "{}: {}".format(self.name, self.value)

class AttributeWithMaxValue(Attribute):
    def __init__(self, atr_value, atr_name, max_value):
        Attribute.__init__(self, atr_value, atr_name)
        self.max_value = max_value

    def improve_for_newround(self):
        self.max_value += random_value() + random_value()
        self.value = self.max_value

    def __str__(self):
        return "{}: {}/{}".format(self.name, self.value,self.max_value)
ich habe noch die ID entfernt, weil überflüssig, eine Attribut mit Maximalwert eingeführt und eine __str__-Methode hinzugefügt, z.B. für:

Code: Alles auswählen

    def details(self, game_round):
        print("\n\tName: {0} \t\t Level: {1}".format(self.name, self.level))
        print("\tExp: {0}/{1} \t\t Round:".format(self.exp,
            self.exp_levelup, game_round))
        print("\n{}\t{}\n{}\t{}\n".format(self.strength, self.vitality, self.dextery, self.defense)
Benutzeravatar
kevind
User
Beiträge: 71
Registriert: Montag 22. Oktober 2012, 20:23
Wohnort: /dev/null

Genial, danke!

Ich hab mir in der zwischenzeit auch das __str__ statement angeschaut. Dies ist aber auch nur anwendbar wenn die Methode 1 String zurückgeben soll oder?

Wenn ich jetzt das Menü neu aufbaue möchte. Müsste ich dann die Game Instanz von Menüpunkt zu Menüpunkt übergeben oder wie stell ich sowas ordentlich an ?

Kann mir da jemand ein bischen "Starthilfe" geben :) ?

Gruss, Kev
Benutzeravatar
kevind
User
Beiträge: 71
Registriert: Montag 22. Oktober 2012, 20:23
Wohnort: /dev/null

Servus,

meine Character Klasse arbeitet mit den Werten der Attribute Klasse. Nun möchte ich vermeiden das ich innerhalb der Character Klasse direkt auf die Attribute zugreife. (Klassen sollen ja nichts über das Innenleben einer anderen Klasse wissen oder ?)

Nun würde ich gerne zb folgendes machen:

Code: Alles auswählen

damage = character.atk - character.defense
um dieses hier zu vermeiden:

Code: Alles auswählen

damage = character.atk.value - character.defense.value
Ich dachte ich könnte das irgendwie mit der __str__ methode lösen aber das funktioniert nicht.

Die Attribut Klasse sieht momentan so aus:

Code: Alles auswählen

class Attribute():
    def __init__(self, atr_ID, atr_value, atr_name):
        self.ID = atr_ID
        self.value = atr_value
        self.name = atr_name

    def __str__(self):
        return(self.value)

    def reduce(self, amount):
        self.value -= amount

    def improve(self):
        self.value += 5

    def improve_for_newround(self):
        self.value += random_value() + random_value()

    def is_ID(self, possible_id):
        if self.ID == possible_id:
            return True
        else:
            return False
Danke für eure Ratschläge.

ps: Ja das mit der ID muss ich noch regeln... Eins nach dem Anderen ;)
BlackJack

@kevind: Was hat denn `__str__()` damit zu tun? Das soll eine Zeichenkette zurück geben. Und man müsste dazu dann auch `str()` mit dem Exemplar aufrufen. Zeichenketten kann man schlecht voneinander abziehen.
Benutzeravatar
kevind
User
Beiträge: 71
Registriert: Montag 22. Oktober 2012, 20:23
Wohnort: /dev/null

Ich dachte vl. lässt sich das noch in INT umwandeln. Aber vergessen wir das mal.

Was würde sich für diese Situation am besten eignen ?
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Indem Du __int__ überschreibst, dann kannst Du mit int(...) das Objekt in eine Zahl umwandeln.
Antworten