2016-08-09 3 views
0

Zum Beispiel versuche ich eine gegnerische Klasse für ein einfaches Spiel zu bauen. Jeder Feind, die Spawns hat eine Typ, die es beeinflusst Statistiken, die Felder in der Feind Klasse sind.Wann garantiert eine Klasse eine Unterklasse?

class Enemy: 
    #Base Stats for all enemies 
    name = "foo" 
    current_health = 4 
    max_health = 4 
    attack = 0 
    defense = 0 
    armor = 0 
    initiative = 0 
    initMod = 0 
    alive = True 

Sollte jederTyp eine Unterklasse von Feind wie so .. sein

class goblin(Enemy): 
    name = goblin; 
    current_health = 8 
    max_health = 8 
    attack = 3 
    defense = 2 
    armor = 0 

    def attack(){ 
     //goblin-specific attack 
    } 

Aber diese Methode bedeutet, dass ich eine Klasse für jeden einzelnen Typ bauen müssten (was wäre mehr als 80 Klassen), oder gibt es einen besseren Weg, es zu tun? Dieser Feind wird randomisiert werden, so dass ich dachte, die Typen auch in einen Wörterbuch genommen werden kann, die die Namen der Typen als Schlüsselwörter verwendet. Obwohl ich mir nicht ganz sicher bin, wie ich das umsetzen könnte.

+0

Mit so vielen möglichen Unterklassen modellieren Sie das Problem wahrscheinlich nicht gut. Zum einen klingt es so, als ob du "is-a" mit "has-a" -Beziehungen verwirrst - und möglicherweise Klassen und Instanzen von Klassen. Die meisten der aufgelisteten Attribute werden wahrscheinlich im Konstruktor der Klasse oder der Unterklasse ('__init __()') initialisiert. Außerdem erhalten alle Definitionen von Klassenmethoden automatisch ein erstes Argument, das normalerweise 'self' heißt und die Instanz der Klasse darstellt. Sie müssten also 'def attack (self):' haben. Außerdem verwendet Python '' '' '' '' Klammern nicht auf diese Weise. – martineau

Antwort

0

Wenn Sie das Wörterbuch Weg gehen Sie so etwas wie dies mit einem Tupel tun könnte durch den Schlüssel zurückgegeben werden:

enemy_types = {"goblin": ("goblin", 8, 8, 3, 2, 0, goblin_attack)} 

def goblin_attack(enemy): 
    do_stuff() 

wenn Sie eine named_tuple

https://stackoverflow.com/a/13700868/2489837

verwenden möchten

, um sicherzustellen, dass Sie die Felder im Tupel nicht verwechseln

+0

Ich denke, das ist der Weg, den ich gehen werde. Um das klarzustellen, folgt jeder Feind den gleichen Richtlinien für den Kampf. Sie alle können angreifen oder verteidigen, aber was sie während ihres Angriffs tun, hängt von ihrer speziellen Fähigkeit ab. Müsste ich für jeden Feindtyp in meinem Wörterbuch eine separate Funktion erstellen? Und würden sich diese Funktionen in meiner Feind-Klassendatei befinden? – Czurch

+0

Das muss an dir liegen. Alles, was meine Lösung tut, ist einen Funktionszeiger für jede Funktion zurückzugeben. Abhängig davon, was ihre speziellen Angriffe sind (dh, kannst du einfach einen Parameter übergeben, wie viel Schaden es verursacht, oder hat es mehr spezielle Dinge, die damit verbunden sind), brauchst du vielleicht eine einzigartige Funktion für jeden einzelnen. In beiden Fällen können Sie diese Wörterbuchroute trotzdem verwenden und ein Tupel/Objekt zurückgeben oder was Sie haben. –

0

Wenn die Menge der Attribute und möglichen Aktionen für jeden Feind Typ Das ist meistens bei allen Typen der Fall. Ich sehe keinen Grund, etwas Komplizierteres zu tun, als eine 80-Item-Enumeration für den Typ zu definieren und eine einzige Klasse namens Enemy zu verwenden.

Wenn Sie eine Vielzahl von Aktionen tun müssen, und solche, vielleicht könnten Sie Ihre Gruppe 80 Arten in verschiedenen Sammlungen, die dann gemeinsame Attribute aufweisen würde (zum Beispiel FlyingEnemy, UndeadEnemy, etc). Diese würden dann zu deinen Unterklassen werden.

+0

Ich mag diese Idee wirklich, könnte es auch mit der Idee von user2489837 funktionieren, ein Wörterbuch für verschiedene Gegner zu benutzen? So könnte ich eine Liste von FlyingEnemies oder UndeadEnemies haben. – Czurch

0

Der Goblin sollte wahrscheinlich eine Instanz von Feind sein. In Ihrem Beispiel haben Sie jedoch eine Methode namens attack hinzugefügt. Ich würde sagen, der beste Weg, dies zu tun, ist wie folgt:

class Enemy: 
    #Base Stats for all enemies 
    def __init__ (self, **kwargs): 
    self.name = "foo" 
    self.current_health = 4 
    self.max_health = 4 
    self.attack = 0 
    self.defense = 0 
    self.armor = 0 
    self.initiative = 0 
    self.initMod = 0 
    self.alive = True 
    # Use this to specify any other parameters you may need 
    for key in kwargs: 
     exec ("self.%s = %s" % (key, kwargs[key]) 

Jetzt können Sie eine Instanz von Enemy namens Goblin erstellen.

Um Ihre erste Frage zu beantworten, wann eine Unterklasse zu verwenden ist, würde ich sagen, dass es großartig ist, Unterklassen zu verwenden, aber in Ihrem Fall die Dinge komplizierter machen kann. Da Sie nur eine Methode in Ihrer Unterklasse haben, können Sie einfach ein Modul erstellen und dann ein Argument in __init__ haben, das die attack-Funktion angibt. Dies wird Ihren Code mehr vereinfachen.

Hinweis: Wenn Sie Subklassen werden sicherstellen, verwenden, dass Sie in der __init__ Ihrer Unterklasse mit super() die __init__ Ihrer Basisklasse aufrufen.

+0

Die gesamte 'for'-Schleife am Ende könnte durch 'self .__ dict __. Update (kwargs)' ersetzt werden. Im Allgemeinen möchte man vermeiden, 'exec' zu verwenden, wann immer es möglich ist, und es ist üblich. Ihr Einzug ist ebenfalls inkonsistent (und nicht 4 Leerzeichen, siehe [PEP 8 - Stilleitfaden für Python-Code] (https://www.python.org/dev/peps/pep-0008/)). – martineau

+0

Ich entschuldige mich für meinen Mangel an Wissen über Wörterbücher, aber ich denke, ich verstehe, was Sie hier tun. Also hätte ich ein Wörterbuch mit all den verschiedenen Gegnertypen definiert. Wenn ich eine neue Instanz eines Feindes erstelle, muss ich den Schlüssel für einen dieser Feinde eingeben. Dieser Schlüssel wird verwendet, um auf einen Typ im Wörterbuch zu verweisen, der die feindlichen Felder auf die im Wörterbuch angegebenen Werte initialisiert. p.s. Danke, dass du dir die Zeit genommen hast zu antworten – Czurch

Verwandte Themen