我不完全确定如何说出这个问题,所以我会坚持解释我的具体目标。
我正在尝试为user_input函数实现'eat'选项以进行文本冒险。我希望它检查动词是否“吃”,检查项目是否在玩家的库存中,检查项目是否可以消费,然后 - 我的目标 - 显示玩家吃掉它(并且只显示它< em>一次,见下文)。 'eat'选项目前还没有功能,我只测试打印语句。
我完全清楚下面的代码不是处理用户输入的最有效方法(我仍在调整处理意外输入的方法),所以我百分之百地批评。这只是我处理它的最初方式,我想尝试使它工作。我有一些其他的动词('去','看','带'等等)有效,我只是在'吃'时遇到很多麻烦。
def user_input(self):
player = Player()
while True:
user_input = input("> ").lower()
words = user_input.split(" ")
wordlist = list(words)
verb = wordlist[0]
if len(wordlist) == 2:
noun = wordlist[1]
if noun not in items:
print("Somehow '{}' isn't the right word.".format(noun))
continue
else:
pass
# The above works fine because I don't have
# an issue with any of the other verbs regarding
# that bit of code.
# There's more code between these blocks to:
# handle if the user enters a noun that is > 1 word,
# define a few more verbs,
# then,
if verb == "eat":
for item in player.inventory:
if item.name == noun:
if isinstance(item, Consumable):
print("You eat the {}.".format(noun))
break
else:
print("You can't eat that!")
break
else:
print("You don't have '{}'.".format(noun))
我不得不使用for循环(至少,我认为我必须这样做),因为我正在迭代一个包含对象的列表,而不是字符串,所以我不能只使用
if noun in player.inventory:
(我仍然尝试了百万次,但是为这个问题提出解决方案需要花费很长时间。这是我上面代码的具体示例:
class Fists(Weapons):
def __init__(self):
self.name = "fists"
# more instance variables for Fists()
class LeatherWallet(Classy):
def __init__(self):
self.name = "leather wallet"
# more ...
class Pizza(Consumable):
def __init__(self):
self.name = "pizza"
# more ...
class Player():
def __init__(self):
self.inventory = [Fists(), LeatherWallet(), Pizza()]
# other stuff
*吃拳头
You can't eat that!
*吃皮革钱包
You don't have 'leather wallet'.
You can't eat that!
*吃披萨
You don't have 'pizza'.
You don't have 'pizza'.
You eat the pizza.
从它的外观来看,它已经得到是一个简单的修复,因为它清楚地发生在迭代列表时发生了什么。我只是不知道如何(或者你是否可以)争论一个for循环使它先检查条件然后再打印。听到愚蠢的风险,我求助于你们所有人!
谢谢,如果我能更明确地提出这个问题/我的目标,请告诉我。
修改 试图在打开段落时使目标更加清晰。
答案 0 :(得分:1)
你不是说你想要输出的是什么,但我最好的猜测是你不想多次说“你没有X”。
执行此操作的一种方法是使用标记,初始化为false,在找到项目时设置为true。当你离开循环时,标志会告诉你是否找到了它。
这样的事情:
if verb == "eat":
found = false
for item in player.inventory:
if item.name == noun:
found = true
if isinstance(item, Consumable):
print("You eat the {}.".format(noun))
break
else:
print("You can't eat that!")
break
if !found:
print("You don't have '{}'.".format(noun))
答案 1 :(得分:1)
for
循环有else
个子句,如果循环没有中断退出则会运行。这个想法是循环正在寻找一个项目,它会在找到它时中断,else
子句处理你找不到你想要的东西的默认情况。循环内部使用的变量在循环结束后仍然有效,因此找到的(或默认的)变量可用于下一位代码。
在您的情况下,如果您将最后一个else子句移出一个级别,它将仅在找不到该项时运行。在您的示例输出中,将不再打印两个“您没有'pizza1”行。
for item in player.inventory:
if item.name == noun:
if isinstance(item, Consumable):
print("You eat the {}.".format(noun))
break
else:
print("You can't eat that!")
break
else:
print("You don't have '{}'.".format(noun))
item = None # <-- you can give a default value if you want to
# use the variable later
在列表变大之前,循环遍历列表是可以的。然后,最好使用dict
为列表编制索引,以便更快地查找。
self.inventory = dict((item.name, item)
for item in (Fists(), LeatherWallet(), Pizza()))
然后将for循环替换为
try:
item = player.inventory[noun]
if isinstance(item, Consumable):
print("You eat the {}.".format(noun))
else:
print("You can't eat that!")
except KeyError:
print("You don't have '{}'.".format(noun))
答案 2 :(得分:0)
所以,另一种方法是让这项工作,对吧?
if noun in player.inventory:
...
你(至少)有两种方法可以做到。
第一个也很容易使用list comprehension:
inventory_items = [item.name for name in player.inventory]
if noun in inventory_items:
...
那就是它。
第二个是创建一个继承自list
并覆盖__contains__
方法的Inventory
类,以便您可以根据需要对它们进行比较。
类似的东西:
class Inventory(list):
def __contains__(self, item):
"""
Override `list.__contains__`.
"""
# First, check whether `item` is in the inventory.
#
# This is what a normal `list` would do.
if list.__contains__(self, item):
return True
# If we couldn't find the item in the list searching
# the "normal" way, then try comparing comparing it
# against the `name` attribute of the items in our
# inventory.
for inventory_item in self:
# Ensure we can do `inventory_item.name` so we don't get
# an AttributeError.
if 'name' not in dir(inventory_item):
continue
if inventory_item.name == item:
return True
return False
然后您实例化您的广告资源,如:
self.inventory = Inventory([Fists(), LeatherWallet(), Pizza()])
请注意,Inventory
继承自list
,因此,如果您可以执行list(x)
,那么您还应该能够执行Inventory(x)
并获得非常相似的结果(取决于你在课堂上覆盖了多少。)
您还可以获得广告素材,并将所有项目从Item
类继承,您可以在其中定义__eq__
方法,并使Pizza() == 'pizza'
简化Inventory
比较。