So, I'm trying to create a game. In this mechanic of the game the user is trying to use an item from the dictionary.
inventory = {
"Health": ["Potion", "Hi-Potion","Elixer"],
"Weapons": ["Blade","Dagger","Staff"],
"Items": ["Glass", "Paper","Notes"],
"Components": ["Rusty Trombone"],
}
# Add and Use item
def add_to_inventory(item_type, item_name):
inventory[item_type].append(item_name)
def use_item():
for item_type, item_name in inventory.items():
print(item_type.title(),":",item_name)
use_item = input("What will you use? \n").title()
if use_item in inventory["Health"]:
position = inventory["Health"].index(use_item)
print(f"You've used {use_item}. {use_item} will now be discarded.")
return inventory["Health"].pop(position)
elif use_item in inventory["Weapons"]:
position = inventory["Weapons"].index(use_item)
print(f"You've used {use_item}. {use_item} will now be discarded.")
return inventory["Weapons"].pop(position)
elif use_item in inventory["Items"]:
position = inventory["Items"].index(use_item)
print(f"You've used {use_item}. {use_item} will now be discarded.")
return inventory["Items"].pop(position)
elif use_item in inventory["Components"]:
position = inventory["Compoents"].index(use_item)
print(f"You've used {use_item}. {use_item} will now be discarded.")
return inventory["Components"].pop(position)
use_item()
There's much redundancy, but I'm having trouble finding how to shorten my code.
With the use_item function I want to first have the entire inventory on view for the user to make choosing what to use easier. Then is the prompt to use the item. I want to keep the title method for all strings in future cases where multiple word items would need it's first letter capitalized. Using the position variable allows me to obtain the indexed position of the item being used. This allows me to use the pop method to not only discard the item from the inventory, but to return that item for its intended use (A key to open a door, using a weapon, recovering health, tinkering).
All mechanics haven't been coded yet, but the more I look at this portion the more I feel it can be done much better. I'm stumped on how to though.
I was considering iterating through each key value pair, then discarding the item from the dictionary. But, I need the pop method to return the item in question (and end the function). I ran into trouble from the key having a list value. The value being a list makes it easier to navigate through, but also presents the issue of needing further iteration - maybe with a nested for loop? But then I'm not sure how to implement that to work for this situation.
CodePudding user response:
Since you're doing the same thing for each key in the dictionary, you could use a for
loop instead:
for key in inventory:
if use_item in inventory[key]:
position = inventory[key].index(use_item)
print(f"You've used {use_item}. {use_item} will now be discarded.")
return inventory[key].pop(position)
CodePudding user response:
As you are repeating the same action multiple times, you could move it to a function in a
for
loop..remove()
does theindex
andpop
in one method
def discard(user_item, inventory):
for k, v in inventory.items():
if user_item in v:
print(
f"You've used {user_item}. {user_item} will now be discarded.")
inventory[k].remove(user_item)
return user_item
def use_item():
for item_type, item_name in inventory.items():
# Join will join elements nicely
# Use an f string to easily edit string format
print(f"{item_type.title()}: {', '.join(item_name)}")
# Try not to name variables after your function name
user_item = input("What will you use? \n").title()
discard(user_item, inventory)
Other suggestions have been commented in