When you play a board game like "munchkin" for example, you will have a pile of item cards in stock, in each players hand and maybe in a room. Those item cards are physically unique and drawn from the pile, added to a players inventory and finally discarded to a pile.
Big RPGs do "in a very very simplified way" the same, A designer places an item in the game, it gets certain unique ID that in the past sometimes caused trouble to identify those items and make lookups (has a palyer taken the item then remove it from the initial level state to get the level back to its 'saved' state, place it in the world at certain location if a player dropped it, place it in inventory of NPC xy if he sold/gave it to that NPC ...) so what I would do for your simple case is to generate an item ID for each item in each 'room' or level starting by some bytes to identify the place the item cames from, the item itself and maybe some other information.
An ID could then look like this
UInt64 CreateId(UInt16 location, UInt16 itemClass, UInt32 flags)
{
return ((location << 62) | (itemClass << 60) | flags);
}
I've used the location as the left most 2 bytes followed by 2 bytes for an item class that may be your sword, bow, dagger, whatever as pattern and added additional 4 bytes as state bits. Those state bits may be used in your pattern for example
...
class Sword : Item
{
//inherited from parent class
public UInt64 Id
{
get;
private set;
}
public bool IsLongSword
{
get { return (Id & 0x1);}
}
public bool IsShortSword
{
get { return (Id & 0x2);}
}
public bool IsRusty
{
get { return (Id & 0x4);}
}
public bool IsEnchanted
{
get { return (Id & 0x8);}
}
}
...
Item[] item = Room.GetItems(ItemClasses.Sword);
...
class Room
{
//item id <> count in the room
Dictionary<UInt64, UInt32> items = new Dictionary<UInt64, UInt32>();
GetItems(ItemClass targetItemClass)
{
List<Item> result = new List<Item>();
foreach(UInt64 id in items)
{
// Bitmask to select the parts of the id, Room Id 2 Byte, Item Class 2 Byte, Flags 4 Byte
// |RID| IC|Flags |
UInt16 itemClass = (id & 0x0000FFFF00000000);
if((ItemClass)itemClass == targetItemClass)
result.Add(new Item(id));
}
return result.ToArray();
}
}
So you could always identify your items by its id, its class and parent room also, usefull when dropping an item and for stacking (you need to increase count by id, should not be too difficult in your kind of game).
To identify your items by certain name is risky because you could misspell the name for failure and will never get the right item so you need to debug the code, also strings are wasting memory and using a 2 byte enum is much more memory friendly here. Big games do this too by hashing certain string-names to a 4 byte integer value for example. Integers are also more hash-collection friendly (as they are just integers you will not waste time for a hashing function to covnert them).
Using hash-containers like Dictionary or HashTable you will safe a lot of lookup time for targeting single Ids (while seeking for all items of certain type is still an O(n) operation)