Best way to store a list/array of different subclasses
I am trying to write a program to simulate a card game. I have class called MagicCard, and a variety of classes that extend card, like card1, card2... I want to find a way to store a list/array of different cards (a deck). Each card1, card2... has a "special" effect that they trigger when they are played, so the need a unique function, which is why i need all the different subclasses. A lot of the cards have a similar properties. How can I store the deck in a reasonable and accessible manner? (I want the deck to easily be manipulated so I can add a card, or remove a card from it when I want).
Currently this is what I have:
//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
}
Is there a better way to implement this? Also the code does not work as it tells me WallOfOmens and Card2 do not implement SpecialEffect(), why is that happening?
I would consider an alternative, use composition instead of inheritance. Composition is more flexible than inheritance, it allows you to combine different aspects more freely than inheritance.
Instead of creating
abstract class BaseCard{abstract int SpecialEffect();}
class Card1 : BaseCard{override int SpecialEffect(){return 1;}}
class Card2 : BaseCard{override int SpecialEffect(){return 2;}}
...
you create different SpecialEffect-classes
abstract class SpecialEffectBase{abstract int SpecialEffect();}
class SpecialEffect1 : SpecialEffectBase{override int SpecialEffect(){return 1;}}
class SpecialEffect2 : SpecialEffectBase{override int SpecialEffect(){return 2;}}
...
and assemble the different cards in a factory
Card card1 = new Card(new SpecialEffect1());
Card card2 = new Card(new SpecialEffect2());
This might sound like just another step of indirection, but if you reuse several some effects in different cards, and have other properties that differ between cards, like Rules or something you can assemble them like this
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());
...
Another benefit is that it forces you to encapsulate the SpecialEffect-rules in the SpecialEffect-classes, the Rule-rules in the Rule-classes, etc. instead of having them all over the place in your Card class.
You have misspelt SpecialEffect
in the classes that implement that interface. Fixing the typo should help.
Once you have the compilation working you can store MagicCard
instances in any (preferably generic) container.
It might be helpful to extend the MagicCard
interface so that it has a property that returns the object as cardProperties
, for easy accessibility. Dual inheritance makes it more tricky to access both the base class and interface for a container element, since you can only store one Type in the generic container. It seems a fair bet that any MagicCard
will have cardProperties
.
Use a List class. where T is cardProperties or MagicCard Also, instead of using an interface, why don't you remove the interface MagicCard and add the int SpecialEffect(); as an abstract method to cardProperties:
public abstract int SpecialEffect();
abstract methods must be implemented by subclasses, then u have to mark the cardProperties as abstract too
I personally would have made MagicCard
as a parent class, and not as an interface. In it, you can declare SpecialEffect
as virtual to allow overrides even if it's not required. Then, in your deck class, you can use a List<MagicCard>
object, just as andrewjs suggested.
Perhaps look up Polymorphism.
Ideally you should store a List<Card>
. All the different cards inherit from your base class Card
, and some cards implement an interface called IMagicCard
.
Alternatively, if there's only one type of MagicCard
, it could directly inherit from Card
So, you could Have:
Card
WizardCard : Card, IMagicCard
WitchCard : Card, IMagicCard
HumanCard : Card
Or
Card
MagicCard : Card
NonMagic: Card
I would recommend the former, but depending on how you structure your game, both might be applicable.
You'll have to excuse me if I misunderstood your intent.
精彩评论