在我的库存系统中创建可堆叠物

时间:2014-09-17 17:21:37

标签: c# unity3d

尝试构建包含可堆叠的库存系统时。除了 stackables 部分之外,库存系统运行良好。

现在,由于无限循环,我已经完全停止了。

这里是代码,带有评论,希望您能够理解我想要完成的任务。

    void AddItem(int id, int count) 
    {
    while(count > 0) // Continue running as long as there is an item to be added
    {
        for(int i = 0; i < inventory.Count; i++) // Search through the inventory
        {
            if(inventory[i].itemID == id) // We've found an item with the appropriate ID
            {
                int maxAdd = inventory[i].itemMaxStack - inventory[i].itemCurrStack; // Figure out how much we can add to this stack

                if(count > maxAdd) // There's not enough room to fit the entire stack, so add what we can and continue the -for- loop
                {
                    inventory[i].itemCurrStack = inventory[i].itemMaxStack;
                    count -= maxAdd;
                    continue;
                }

                if(count <= maxAdd) // There's enough room to fit the entire stack, so add it in.
                {
                    inventory[i].itemCurrStack += count;
                    count = 0;
                }

                if(inventory[i].itemCurrStack == inventory[i].itemMaxStack) // We found a stack, but it's already full, so continue the -for- loop
                {
                    continue;
                }
            } else if(inventory[i].itemName == null) // There were no items with the specified ID, so let's create one.
            {
                for(int j = 0; j < database.items.Count; j++)
                {
                    if(database.items[j].itemID == id)
                    {
                        inventory[i] = database.items[j];
                        break; // Break out of the -for- loop, since we've found what we're looking for.
                    }
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:4)

你真的不需要用循环来做这件事。您可以只堆叠源和目标的最大值之间的差异,如果有任何剩余,只需将其作为新堆栈转储到库存中。

编辑:根据您的评论添加更多管道以澄清。这与您的原始问题有很大不同,但它证明了我的观点。

public abstract class Loot
{
    public int Count { get; set; }
    public virtual int MaxCount { get; set; }
}

public class Inventory : ICollection<Loot>
{
    public void Stack(Loot source, Loot target)
    {
        var availableOnTarget = target.MaxCount - target.Count;
        var amountToStack = Math.Min(availableOnTarget, source.Count);
        target.Count += amountToStack;
        source.Count -= amountToStack;
        if (target.Count == target.MaxCount && source.Count > 0)
        {
            this.Add(source);
        }
    }

    // ICollection implementation...
}

// This could be in Inventory, or the Player, or a gameplay manager...
// Personally I'd implement it in the Inventory class, if there was only
// one player with only one inventory. I'm sticking to the semantics of
// my first version, though.
public class Caller
{
    public void TryAddItemToInventory<TLoot>(Inventory inventory, TLoot itemToAdd) where TLoot:Loot
    {
        var sourceType = itemToAdd.GetType();
        var stackTarget = inventory.OfType<TLoot>().First(i => i.Count < i.MaxCount);
        if (stackTarget != null)
        {
            inventory.Stack(itemToAdd, stackTarget);
        }
        else
        {
            inventory.Add(itemToAdd);
        }

        // You need to check if the inventory exists, if it has enough room to accommodate
        // the item, what happens to overflow, etc. Left all that out for brevity.
    }
}