所以我想做的事情很难在标题中描述。
这就是我想要做的事情: 在下面的代码中,我希望有一些可以在Room类(例如Search,Loot)和Player类(例如quit,heal)上调用的一般方法。我希望这种情况发生的方式是玩家在输入中输入他们想要做的事情,而python将在dict中查找该选项,该选项与方法的选择相匹配。
我已经成功完成了房间出口。我可以通过创建一个子类并在那里列出方法来实现,但我真的不想这样做,因为这看起来很麻烦。
当我运行下面的代码时,它只是自动退出。如果我用第一个字典注释出来运行它,我得到一个错误,说__init __()缺少一个必需的位置参数。
from textwrap import dedent
from sys import exit
class Player(object):
actions = {
'QUIT': quit
}
def __init__(self, actions):
self.actions = actions
# Want actions to be a list of actions like in the Room Class
#
def quit(self):
# Quits the game
exit(0)
class Room(object):
# Description is just a basic room description. No items needed to be added here.
def __init__(self, desc, exits, exitdesc):
self.desc = desc
self.exits = exits
self.exitdesc = exitdesc
# Also want list of general actions for a room here.
def enterroom(self):
#First print the description of the room
print(self.desc)
#Then print the list of exits.
if len(self.exits) > 1:
print(f"You see the following exits:")
for exd in self.exitdesc:
print(self.exitdesc[exd])
elif len(self.exits) == 1:
print(f"There is one exit:")
for exd in self.exitdesc:
print(self.exitdesc[exd])
else:
print("There are no exits.")
# Then allow the player to make a choice.
self.roomactivity()
# Here's what I mean about calling the methods via a dictionary
def roomactivity(self):
while True:
print("What do you want to do?")
choice = input("> ").upper()
if choice in self.exits:
self.exits[choice].enterroom()
#And here's where I want to call actions other than directions.
elif choice in player.actions:
player.actions[choice]
else:
print("I don't understand.")
class VoidRoom(Room):
def __init__(self):
super().__init__(
desc = "ONLY VOID.",
exits = {},
exitdesc = {})
class TestRoom(Room):
def __init__(self):
super().__init__(
desc = dedent("""
This room is only a test room.
It has pure white walls and a pure white floor.
Nothing is in it and you can hear faint echoes
of some mad sounds."""),
exitdesc = {
'NORTH': 'To the NORTH is a black door.',
'SOUTH': 'To the SOUTH is a high window.',
'EAST': 'To the EAST is a red door.',
'WEST': 'To the WEST is a blue door.'},
exits = {
'NORTH': void_room,
'SOUTH': void_room,
'EAST': void_room,
'WEST': void_room})
void_room = VoidRoom()
test_room = TestRoom()
player = Player()
test_room.enterroom()
我希望我已经清楚地解释了这个问题。还在学习这种语言,我现在可能已经咬过的东西比我现在可以咀嚼的还多。
编辑:新代码:
我已经改变了一些东西,我将播放器命令和内容放在一个单独的py文件中,这样我就可以扩展播放器范围,而不会使rooms.py文件变得混乱。
from textwrap import dedent
from sys import exit
from player import *
from enemies import *
# This is the base class for a room.
class Room(object):
# Description is just a basic room description. No items needed to be added here.
def __init__(self, desc, exits, exitdesc, inventory):
self.desc = desc
self.exits = exits
self.exitdesc = exitdesc
self.inventory = inventory
def enterroom(self):
#First print the description of the room
Player.currentroom = self
print(self.desc)
for item in self.inventory:
print(self.inventory[item].lootdesc)
#Then print the list of exits.
if len(self.exits) > 1:
print(f"You see the following exits:")
for exd in self.exitdesc:
print(exd)
elif len(self.exits) == 1:
print(f"There is one exit:")
for exd in self.exitdesc:
print(exd)
else:
print("There are no exits.")
# Then allow the player to make a choice.
self.roomactivity()
def roomactivity(self):
while True:
print("What do you want to do?")
choice = input("> ").upper()
if choice in self.exits:
self.exits[choice]().enterroom()
elif choice in Player.actions:
Player.actions[choice]()
else:
print("I don't understand.")
#Player.actions[choice]()
class Room3(Room):
def __init__(self):
super().__init__(
desc = dedent("""
You are in a large, dimly lit room.
Torches sit in empty alcoves, giving off an eerie red glow.
You hear scratching and squeaking from behind the walls."""),
exits = {
'NORTHEAST': StartRoom
},
exitdesc = [
'A sturdy looking door leads to the NORTHEAST'
],
inventory = {})
class Room1(Room):
def __init__(self):
super().__init__(
desc = dedent("""
You are in a medium sized, dimly lit room.
Busts of dead men you don't know sit atop web-strewn pedestals."""),
exits = {
'EAST': StartRoom
},
exitdesc = [
'An arch leading into a dimly lit hall lies to the EAST.'
],
inventory = {'IRON SWORD': iron_sword}
)
class StartRoom(Room):
def __init__(self):
super().__init__(
desc = dedent("""
PLACEHOLDER LINE 49"""),
exits = {
'SOUTHWEST': Room3,
'WEST': Room1
},
exitdesc = [
'An arch leading into a dimly lit room lies to the WEST',
'A sturdy looking door lies to the SOUTHWEST'],
inventory = {}
)
class HelpPage(Room):
def __init__(self):
super().__init__(
desc = dedent("""
All actions will be listed in all caps
When asked for input you may:
QUIT the game
Check your INVENTORY
Check your player STATUS
SEARCH the room
EXAMINE an object or point of interest
USE an item from your inventory or the room
ATTACK a creature
GET an item from the room
or pick a direction (listed in caps)"""),
exits = {},
exitdesc = [
'Press ENTER to return to the Main Menu'],
inventory = []
)
def enterroom(self):
print(self.desc)
for exd in self.exitdesc:
print(exd)
self.roomactivity()
def roomactivity(self):
input()
MainMenu.enterroom()
help_page = HelpPage()
# Main menu, lil bit different from a regular room
class MainMenu(Room):
def __init__(self):
super().__init__(
desc = dedent("""
THE DARK DUNGEON OF THE VAMPIRE KNIGHT
A game by crashonthebeat"""),
exits = {
'START': StartRoom,
'HELP': HelpPage
},
exitdesc = [
'Press START to Start the Game',
'Or go to the HELP Menu'],
inventory = []
)
def enterroom(self):
print(self.desc)
for exd in self.exitdesc:
print(exd)
self.roomactivity()
def roomactivity(self):
while True:
choice = input("Choose an Option: ")
if choice in self.exits:
self.exits[choice]().enterroom()
else:
print("I don't understand")
来自player.py的相关代码
from items import *
from rooms import *
class Player(object):
@property
def actions(self):
actions_map = {
'QUIT': 'quit_',
'STATUS': 'status',
'INVENTORY': 'printinventory',
'EXAMINE': 'examine',
'USE': 'useitem',
'SEARCH': 'searchroom',
'GET': 'getitem',
'CURRENTROOM': 'getcurrentroom'
}
return actions_map
答案 0 :(得分:0)
一种方法是
class Player(object):
actions = {
'QUIT': 'quit'
}
然后
def roomactivity(self):
while True:
[...]
elif choice in player.actions:
getattr(player, player.actions[choice])()
答案 1 :(得分:0)
我看到一些潜在的问题:
quit
来自Player actions
字典?它被表示为某种已知的名称(变量/方法/对象),但是您定义quit的唯一时间是作为Player的方法,因此类属性actions
无法访问它。
quit永远不会被调用。例如,当用户输入“QUIT”执行player.actions[choice]
时,即使quit
确实存在,也只返回它指向的任何函数。它没有调用那个功能。这是不好的。 player.actions[choice]()
会帮助你。
在脚本中定义变量并在类中引用脚本变量是禁忌。可以让你的类方法调用VoidRoom()或TestRoom(),但是让它从一个完全不同的命名空间引用变量test_room
和void_room
,而不是那么多。
见下面的例子:
actions = {
'QUIT': quit
}
这不会退出您的计划。 “quit”也是python IDLE中的保留字,因此不是方法的最佳选择。 Python约定是在末尾放置一个'_'以避免与保留字冲突:quit_
。我会完全删除该属性并使其成为属性,因此您可以在其子代中覆盖它并添加额外的功能。您牺牲了使用自定义操作初始化玩家的能力,但是那些具有相关操作的类不会更有意义吗?
class Player(object):
@property
def actions(self):
actions_map = {
'QUIT': self.quit_
}
return actions_map
def quit_(self):
print("Quitting the game.")
exit(0)
class PlayerThatCanSing(Player):
@property
def actions(self):
default_actions = super().actions # We still want Player actions
new_actions = {
'SING': self.sing
}
combined_actions = new_actions.update(default_actions) # Now player can quit AND sing
return combined_actions
def sing(self):
print("Do Re Ma Fa So La Te Do")
现在引用player.actions['QUIT']()
会调用player.quit_,这就是你想要的。
关于#3:
class TestRoom(Room):
def __init__(self):
super().__init__(
desc = dedent("""
This room is only a test room.
It has pure white walls and a pure white floor.
Nothing is in it and you can hear faint echoes
of some mad sounds."""),
exitdesc = {
'NORTH': 'To the NORTH is a black door.',
'SOUTH': 'To the SOUTH is a high window.',
'EAST': 'To the EAST is a red door.',
'WEST': 'To the WEST is a blue door.'},
exits = {
'NORTH': void_room,
'SOUTH': void_room,
'EAST': void_room,
'WEST': void_room})
void_room = VoidRoom()
test_room = TestRoom()
player = Player()
您在脚本运行时声明void_room
和test_room
,这很好。唯一的问题是你的课程对你的运行时变量一无所知,所以如果你想让North,South,East和West映射到VoidRoom的一个实例(这是一个TestRoom知道的类,因为它就坐在上面它在模块中),直接引用VoidRoom(),而不是void_room。永远不要假设您的课程对该课程之外发生的任何有任何了解,并且没有被传递到该课程的__init__
。
我希望带有actions属性的Player示例(在这种情况下只考虑属性作为将函数作为变量引用的方法 - 因为操作返回dict
,我们可以将其视为{{{ 1}}没有用actions()调用方法。dict
将返回dict,漂亮且可读)是有道理的,因为如果你以这种方式实现它,你可以拥有特定类型的bards继承许多层,调用player.actions
(他们的父类)的覆盖操作意味着即使是最具体的DwarfBlacksmithWhoSingsInHisSpareTime类也会一直获取所有父操作(因为每个操作方法都会调用其父操作,并且一直打开它直到它命中玩家),所以你得到一个可以戒掉,唱歌和铁匠的矮人。非常优雅,我希望它不会太混乱,因为它是一个非常酷的概念。祝你好运!