2010-11-19 4 views
0

J'essaie d'écrire un programme pour simuler un jeu de cartes. J'ai une classe appelée MagicCard, et une variété de classes qui étendent la carte, comme card1, card2 ... Je veux trouver un moyen de stocker une liste/tableau de cartes différentes (un deck). Chaque carte1, carte2 ... a un effet "spécial" qu'elles déclenchent quand elles sont jouées, donc le besoin d'une fonction unique, c'est pourquoi j'ai besoin de toutes les différentes sous-classes. Beaucoup de cartes ont des propriétés similaires. Comment puis-je stocker le jeu de manière raisonnable et accessible? (Je veux que le jeu soit facilement manipulé pour que je puisse ajouter une carte, ou en retirer une carte quand je veux).Meilleure façon de stocker une liste/tableau de sous-classes différentes

Actuellement c'est ce que j'ai:

//My Code 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace mtgDeckSimulator 
{ 

    //General properties of a magic card, extended by individual classes 
    class cardProperties 
    { 
     private String cardName; 
     /*Mana Array Aranged in the following Order: 
     * [Colorless,White,Blue,Black,Red,Green] */ 
     private int[] manaCost; 
     /* Card Type int definitions: 
     * 0-Artifact 
     * 1-Creature 
     * 2-Enchantment 
     * 3-Instant 
     * 4-Land 
     * 5-Planeswalker 
     * 6-Sorcery 
     * 7-Tribal */ 
     private int cardType; 
     public int attack; 
     public int defense; 
     private bool permBool; 
     private bool isLegen; //Or is restricted to one copy 
     public cardProperties(String cardName,int[] manaCostIn,int cardTypeIn,int attack,int defense,bool permBoolIn,bool isLegenIn) 
     { 
      this.cardName = cardName; 
      manaCost = manaCostIn; 
      cardType = cardTypeIn; 
      permBool = permBoolIn; 
      isLegen = isLegenIn; 
     } 
     //Get Variables 
     public String getCardName() 
     { 
      return cardName; 
     } 
     public int[] getManaCost() 
     { 
      return manaCost; 
     } 
     public int getCardType() 
     { 
      return cardType; 
     } 
     public bool getPermBool() 
     { 
      return permBool; 
     } 
     public bool getIsLegen() 
     { 
      return isLegen; 
     } 
     //Other Methods 
    } 

    //Interface for magic cards 
    interface MagicCard 
    { 
     int SpecialEffect(); 
    } 
    #region Magic Card List 
    class WallOfOmens : cardProperties, MagicCard 
    { 
     public WallOfOmens() 
      : base("Wall of Omens", new int[6] { 1, 1, 0, 0, 0, 0 }, 1, 0, 4, true, false) 
     { 
      ; 
     } 
     public int SpecialEfect() 
     { 
      return 1; 
      //throw new NotImplementedException(); 
     } 
    } 
    class Card2 : cardProperties, MagicCard 
    { 
     public int SpecialEfect() 
     { 
      return 2; 
      //throw new NotImplementedException(); 
     } 
    } 
    #endregion 
} 

Y at-il une meilleure façon de mettre en œuvre ce? Aussi le code ne fonctionne pas car il me dit que WallOfOmens et Card2 n'implémentent pas SpecialEffect(), pourquoi cela se passe-t-il?

+2

Si vous épelez 'SpecialEfect' comme' SpecialEffect' comme dans l'interface, cela pourrait fonctionner mieux. –

+0

Parce que vous ne dites pas que vos fonctions implémentent l'interface. Ils devraient être appelés MagicCard.SpecialEffect() – Stu

+0

@Stu: En C#, vous n'avez pas besoin de qualifier l'interface sauf si elle est ambiguë (c'est-à-dire, plusieurs interfaces avec le même membre) –

Répondre

4

Je considérerais une alternative, utiliser la composition au lieu de l'héritage. La composition est plus flexible que l'héritage, elle vous permet de combiner différents aspects plus librement que l'héritage.

Au lieu de créer

abstract class BaseCard{abstract int SpecialEffect();} 
class Card1 : BaseCard{override int SpecialEffect(){return 1;}} 
class Card2 : BaseCard{override int SpecialEffect(){return 2;}} 
... 

vous créez différentes SpecialEffect classes

abstract class SpecialEffectBase{abstract int SpecialEffect();} 
class SpecialEffect1 : SpecialEffectBase{override int SpecialEffect(){return 1;}} 
class SpecialEffect2 : SpecialEffectBase{override int SpecialEffect(){return 2;}} 
... 

et assembler les différentes cartes dans une usine

Card card1 = new Card(new SpecialEffect1()); 
Card card2 = new Card(new SpecialEffect2()); 

Cela peut sembler juste une autre étape de indirection, mais si vous réutilisez plusieurs effets dans différentes cartes, et ses propriétés qui diffèrent entre les cartes, comme les règles ou quelque chose que vous pouvez les assembler comme ce

Card card1 = new Card(new SpecialEffect1(), new Rule1()); 
Card card2 = new Card(new SpecialEffect1(), new Rule2()); 
Card card3 = new Card(new SpecialEffect2(), new Rule1()); 
Card card4 = new Card(new SpecialEffect2(), new Rule2()); 
... 

Un autre avantage est qu'il vous oblige à encapsuler les SpecialEffect règles dans les SpecialEffect classes, la règle des règles dans la règle -classes, etc. au lieu de les avoir partout dans votre classe Card.

+0

Il me donne une erreur avec votre code, en soulignant le retour et en disant "type attendu". Qu'est-ce que je fais mal? (sry je suis assez nouveau pour coder). – chetjan

+0

Cela semble fonctionner si je remplace (return 1;) par {return 1;} donc cela semble fonctionner maintenant. – chetjan

+0

@chetjan, désolé, je l'ai réparé maintenant –

1

Vous avez mal orthographié SpecialEffect dans les classes qui implémentent cette interface. La correction de la faute de frappe devrait aider.

Une fois que la compilation fonctionne, vous pouvez stocker MagicCard instances dans n'importe quel conteneur (de préférence générique).

Il peut être utile d'étendre l'interface MagicCard afin qu'elle ait une propriété qui renvoie l'objet sous la forme cardProperties pour faciliter l'accès. L'héritage double rend plus difficile l'accès à la fois à la classe de base et à l'interface d'un élément conteneur, puisque vous ne pouvez stocker qu'un type dans le conteneur générique. Il semble un pari juste que n'importe quel MagicCard aura cardProperties.

0

Utilisez une classe List. où T est cardProperties ou MagicCard Aussi, au lieu d'utiliser une interface, pourquoi ne pas supprimer l'interface MagicCard et ajouter l'int SpecialEffect(); comme méthode abstraite de cardProperties:

public abstract int SpecialEffect();

méthodes abstraites doivent être mises en œuvre par les sous-classes, alors u doivent marquer les cardProperties comme abstraites trop

0

regarder peut-être jusqu'à Polymorphism. Idéalement, vous devriez stocker un List<Card>. Toutes les différentes cartes héritent de votre classe de base Card, et certaines cartes implémentent une interface appelée IMagicCard.

Sinon, s'il n'y a qu'un seul type de MagicCard, il pourrait directement hériter de Card

Donc, vous pourriez avoir:

Card 
WizardCard : Card, IMagicCard 
WitchCard : Card, IMagicCard 
HumanCard : Card 

Ou

Card 
MagicCard : Card 
NonMagic: Card 

Je recommande l'ancien , mais selon la façon dont vous structurez votre jeu, les deux peuvent être applicables.

Vous devrez m'excuser si j'ai mal compris votre intention.

0

Personnellement, j'aurais créé MagicCard en tant que classe parente, et non en tant qu'interface.Dans celui-ci, vous pouvez déclarer SpecialEffect comme virtuel pour autoriser les remplacements, même si cela n'est pas nécessaire. Ensuite, dans votre classe de deck, vous pouvez utiliser un objet List<MagicCard>, comme suggéré par andrewjs.

Questions connexes