尝试构建包含可堆叠的库存系统时。除了 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.
}
}
}
}
}
}
答案 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.
}
}