2

My problem is simply that I am creating a small 2D game in C#. This game represents a character that has to kill monsters and gain Experience to increase his level. As his level increases he will be able to wear higher level items as well as his strength points increase he will be able to unlock new items.

How could I restrict some items for specific levels and specific strengths by creating an Item requirements? In the simplest yet powerful way so I don't want to have to involve a large ugly SWITCH or IF ELSE statement.

Note: You can imagine my question as an MMORPG game in which you drop items of different levels and types but only you are able to wear the items that suits your type and level. So simply I want someone to explain me that mechanism and how could I achieve it in C# in a professional way.

4

3 回答 3

4

One approach would be to utilize the Specification pattern.

So, basically, your item would have a WearerSpecification property which returns a specification that returns true if the current character satisfies it.

Something like this:

public abstract class Item
{
    private readonly ISpecification<Character> _wearerSpecification;

    protected Item(ISpecification<Character> wearerSpecification)
    {
        _wearerSpecification = wearerSpecification;
    }

    public ISpecification<Character> WearerSpecification
    {
        get { return _wearerSpecification; }
    }
}

In the method that is called when the character tries to pick up an item, the code would look something like this:

public class Character
{
    public void PickUpItem(Item item)
    {
        if(item.WearerSpecification.SatisfiedBy(this))
        {
            // item can be picked up
        }
        else
        {
            // item can't be picked up
        }
    }
}

To simplify the actual creation of your items and to not repeat your code, you can create concrete specification classes that represent requirements that often occur, e.g. you could create a AtLeastLevel10Specification or a MinimumStrengthSpecification:

public class AtLeastLevel10Specification : ISpecification<Character>
{
    public bool IsSatisfiedBy(Character character)
    {
        return character.Level >= 10;
    }
}

public class MinimumStrengthSpecification : ISpecification<Character>
{
    private readonly int _minimumRequiredStrength;

    public MinimumStrengthSpecification(int minimumRequiredStrength)
    {
        _minimumRequiredStrength = minimumRequiredStrength;
    }

    public bool IsSatisfiedBy(Character character)
    {
        return character.Strength >= _minimumRequiredStrength;
    }
}

You would then possible use these classes directly inside your item declaration:

public class VeryHeavyShield : Item
{
    public VeryHeavyShield()
        : base(CreateSpecification())
    {
    }

    private static ISpecification<Character> CreateSpecification()
    {
        return new AtLeastLevel10Specification().And(
                   new MinimumStrengthSpecification(50));
    }
}
于 2013-07-10T15:22:49.050 回答
3

While Daniel's answer is sound and ultimately more versatile, I think simply implementing a method might be easier to comprehend for a c# beginner. It's definitely better than a huge switch clause.

public class Item
{
    public virtual bool IsWearable(Character c)
    {
        return true;
    }
}

public class BananaSword : Item
{
    public override bool IsWearable(Character c)
    {
         return c.Level >= 10 && c.Race == CharacterRace.BananaWarrior;
    }
}

public class BananaDude : Character
{
    public List<Item> GetWearableItems()
    {
        return AllGameItems.Where(i => i.IsWearable(this)).ToList();
    }
}
于 2013-07-10T15:29:20.197 回答
1

How about creating a "requirement"-array where you pack all your stats. The same array for each item and then iterate through them and set a boolean-false if the stat is to low.

Through this you basically would only have a a>=b check for each value.

于 2013-07-10T15:27:56.370 回答