2

私はゲームのプレーヤーインベントリシステムに取り組んでいます。

どの種類のアイテムが許可されているかを表すList<Loot>コレクションを持つ構造体スロットがあります。抽象クラスLootは、ルート可能なすべてのアイテムによってサブクラス化されます。つまり、Slot構造体の有効なContent値になります。

スロットには、 Lootのどのサブクラスに含めることができるかについて制限があることを表現したいと思います。たとえば、スロットが弾薬コンテナを表す場合、 「矢筒」や「ショットポーチ」(ラインのどこかでコンテナをサブクラス化する)などの弾薬コンテナである戦利品サブクラスのみを保持するようにします。

戦利品クラス

public abstract class Loot : GameEntity, ILootable
{
    public int MaxUnitsPerStack { get; set; }
    public int MaxUnitsCarriable { get; set; }
    public int MaxUnitsOwnable { get; set; }

    public void Stack() { }
    public void Split() { }
    public void Scrap() { }
}

コンテナクラス

public abstract class Container : Loot
{
    public List<Slot> Slots { get; set; }

    public Container(int slots)
    {
        this.Slots = new List<Slot>(slots);
    }
}

スロット構造

public struct Slot
{
    public Loot Content;
    public int Count;
    public List<Loot> ExclusiveLootTypes;

    public Slot(Loot[] exclusiveLootTypes)
    {
        this.Content = null;
        this.Count = 0;

        List<Loot> newList;
        if (exclusiveLootTypes.Count() > 0)
        {
            newList = new List<Loot>(exclusiveLootTypes.Count());
            foreach (Loot l in exclusiveLootTypes)
            {
                newList.Add(l);
            }
        }
        else { newList = new List<Loot>(); }
        this.ExclusiveLootTypes = newList;
    }
}

PlayerInventory

public struct PlayerInventory
{
    static Dictionary<Slot, string> Slots;

    static void Main()
    {
        Slots = new Dictionary<Slot, string>();

        /* Add a bunch of slots */
        Slots.Add(new Slot(/* I don't know the
                              syntax for this:
                              Quiver, Backpack */), "Backpack"); // Container
    }

}

PlayerInventoryクラスのMainメソッドのSlotコンストラクター呼び出しでLootサブクラスの引数を指定する方法がわかりません。

これが明確であることを願っています。前もって感謝します。

編集

私は、David SielerのアプローチといくつかのReflectionを使用して、これを解決することができました(つまり、コンパイルすることができました)。

スロット構造


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

    public struct Slot
    {
        private Loot _content;
        private int _count;
        public List ExclusiveLootTypes;

        public Loot Content
        {
            get { return _content; }
            private set
            {
                if ((ExclusiveLootTypes.Contains(value.GetType())) && (value.GetType().IsSubclassOf(Type.GetType("Loot"))))
                {
                    _content = value;
                }
            }
        }

        public int Count
        {
            get { return _count; }
            set { _count = value; }
        }

        public Slot(params Type[] exclusiveLootTypes)
        {
            this._content = null;
            this._count = 0;

            List newList;
            if (exclusiveLootTypes.Count() > 0)
            {
                newList = new List(exclusiveLootTypes.Count());
                foreach (Type l in exclusiveLootTypes)
                {
                    newList.Add(l);
                }
            }
            else { newList = new List(); }
            this.ExclusiveLootTypes = newList;
        }
    }

スロットコンストラクターへのPlayerInventory呼び出し


Slots.Add(new Slot(typeof(Backpack)));

議論してくれた皆さん、ありがとうございました。

4

4 に答える 4

2

paramsSlotコンストラクターの定義で使用する方が簡単な場合があります。

Slot(params Loot[] exclusiveLootTypes)

これにより、次のように呼び出すことができます。

new Slot(lootItem1, lootItem2, lootItem2 /*...etc*/);

それ以外の場合は、配列を作成して渡す必要があります。

于 2009-12-13T00:39:52.350 に答える
2

オブジェクトのデザインを少し調整する必要があるようです。

戦利品アイテムのタイプもインターフェイスであるとしたらどうでしょう。たとえば、すべての弾薬戦利品アイテムは IAmmoContainer から継承されます。

次に、 IAmmoContainer タイプを渡してスロットを制限できます。

public class Quiver : Container, IAmmoContainer
public class ShotPouch : Container, IAmmoContainer
// ...
new Slot(typeof(IAmmoContainer))

編集

コメントでの議論に基づいて、このシステムを設計する方法を次に示します。

Lootクラスは大丈夫です。戦利品階層のベースを表します。

次に、アイテムが占有できる「スロット」のインターフェースを定義します。例えば:

public class LongSword : Loot, IRightHandItem
public class ShortSword : Loot, IRightHandItem, ILeftHandItem

次に、PlayerInventory クラスには、適切なタイプに制限されたプロパティとして「スロット」があります。

public class PlayerInventory
{
    public List<IRightHandItem> RightHandSlot { get; private set; }
    public List<ILeftHandItem> LeftHandSlot { get; private set; }
    // etc...
}
于 2009-12-13T01:10:01.080 に答える
1

Type1 つのアプローチは、オブジェクトの配列を Slot コンストラクターに渡すことです。

public Slot(Type[] exclusiveLootTypes) {
    // be sure and check that each Type is a subtype of Loot!
}

// Construction looks like:
new Slot(new[] {GetType(AmmoContainer), GetType(GemContainer) /* or whatever */});

次に、割り当てられたオブジェクトのタイプをチェックするプロパティ セッターを記述し、Contentそのタイプが ExclusiveLootTypes に含まれていない場合は何らかのエラーを通知します。

于 2009-12-13T00:43:05.720 に答える
1

以前の提案を組み合わせてパラメーターを使用するには、LINQ 拡張機能を使用して、パラメーターを 1 つのステップでリストに変換できます。

public Slot(params Type[] exclusiveLootTypes)
{
    this.Content = null;
    this.Count = 0;

    this.ExclusiveLootTypes = exclusiveLootTypes.ToList();
}
于 2009-12-13T00:53:30.470 に答える