存储不同子类的列表/数组的最佳方法

时间:2010-11-19 19:24:55

标签: c#

我正在尝试编写一个模拟纸牌游戏的程序。我有一个名为MagicCard的课程,以及各种扩展卡片的课程,比如card1,card2 ......我想找到一种方法来存储不同卡片的列表/数组(甲板)。每个card1,card2 ......都有一个“特殊”效果,它们在播放时会触发,因此需要一个独特的功能,这就是为什么我需要所有不同的子类。很多卡都有类似的属性。如何以合理和方便的方式存放卡座? (我希望可以轻松操作卡座,这样我就可以添加卡片,或者在需要时从卡片中取出卡片。)

目前这就是我所拥有的:

//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
}

有没有更好的方法来实现这个?此外代码不起作用,因为它告诉我WallOfOmens和Card2没有实现SpecialEffect(),为什么会发生这种情况?

5 个答案:

答案 0 :(得分:5)

我会考虑另一种方法,使用组合而不是继承。组合比继承更灵活,它允许您比继承更自由地组合不同方面。

而不是创建

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

你创建了不同的SpecialEffect-classes

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

并在工厂组装不同的卡

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

这可能听起来只是间接的另一个步骤,但是如果你在不同的卡片中重复使用了几个效果,并且在卡片之间有其他不同的属性,比如规则或者你可以像这样组装它们

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());
...

另一个好处是,它会强制您将SpecialEffect规则封装在SpecialEffect类中,规则类中的规则规则等,而不是将它们放在Card类中的所有位置。

答案 1 :(得分:1)

您在实现该界面的类中有拼写错误SpecialEffect。修复拼写错误应该有所帮助。

编译完成后,您可以将MagicCard实例存储在任何(最好是通用的)容器中。

扩展MagicCard接口以使其具有将对象返回为cardProperties的属性可能会有所帮助,以便于访问。双重继承使得访问容器元素的基类和接口变得更加棘手,因为您只能在通用容器中存储一个Type。任何MagicCard都有cardProperties

似乎是公平的赌注

答案 2 :(得分:0)

使用List类。其中T是cardProperties或MagicCard 另外,为什么不删除接口MagicCard并添加int SpecialEffect();而不是使用接口。作为cardProperties的抽象方法:

public abstract int SpecialEffect();

抽象方法必须由子类实现,然后你必须将cardProperties标记为抽象

答案 3 :(得分:0)

或许查找Polymorphism

理想情况下,您应该存储List<Card>。所有不同的卡都继承自基类Card,有些卡实现了一个名为IMagicCard的接口。

或者,如果只有一种类型的MagicCard,则可以直接从Card继承

所以,你可以:

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

Card
MagicCard : Card
NonMagic: Card

我会推荐前者,但根据你的游戏结构,两者都可能适用。

如果我误解了你的意图,你将不得不原谅我。

答案 4 :(得分:0)

我个人原本会将MagicCard作为父类,而不是作为接口。在其中,您可以将SpecialEffect声明为虚拟以允许覆盖,即使它不是必需的。然后,在您的deck类中,您可以使用List<MagicCard>对象,就像andrewjs建议的那样。