2012-09-12 77 views
0

我正在制作基于文本的游戏,并且需要一个可在任何文本输入处拉起的应用程序范围的命令行。我的计划是让命令包含在模块中,并执行command(),然后允许用户输入一个然后运行(包含在同一模块中)的命令(或获取一个列表)。这不起作用,因为我需要一种方式返回到用户所在的位置。无论如何要回到用户在进入命令模式之前的位置,还是有更好的方法来做到这一点?函数运行后返回代码

这是我的想法:

import commands 

def something(): 
    print "a question" 

    action = raw_input("> ") 

    if action == "command": 
     commands.commands() 
    elif "something else" in action: 
     do something 
    else: 
     error.error(1) 
     something() 

然后去commands.py:

def commands(): 
    print "Enter a command, help for a list, blah blah blah." 

    command = raw_input("$ ") 

    if command == "bag": 
     bag() 
    elif command == "other": 
     other() 

def bag(): 
    print "Action listing things in bag" 

问题是返回了用户离开。

+0

大声笑看冒险模块...看看它的来源...也许 –

+0

对不起,我不知道你说什么。谨慎澄清? –

回答

2

你需要的是一个游戏主循环:

while game.is_running: 
    command = get_user_input() 
    user_do(command) 
    update_world() 

这将重复三行代码的while循环内,只要game.is_runningTrue。首先,你得到用户输入。接下来,你采取行动。最后,你执行游戏需要的任何其他更新,例如移动或产生怪物。此时,它循环回来并要求用户输入其他命令。

更新:这里是一个工作示例:

# In commands.py: 
def bag(): 
    print 'bag' 

def other(): 
    print 'other' 

def unrecognized(): 
    print 'unknown command' 

# In main.py: 
import commands 

def user_input(): 
    print 'a question' 
    return raw_input('>') 

def user_do(command): 
    # get the matching command out of commands, or pass back 
    # the unrecognized function if it's not found 
    action = getattr(commands, command, commands.unrecognized) 
    action() 

is_running = True 
while is_running: 
    command = user_input() 
    if command == 'quit': 
     is_running = False 
    else: 
     user_do(command) 

在这个例子中,我已经被骗和我依靠用户输入的命令是相同的函数的名称被调用。在user_do中,getattr调用将用户输入的字符串与command模块的内容进行比较,如果存在相同名称的函数,则返回相同的函数;如果不存在,则返回后备功能unrecognizedaction现在将保存命令功能或unrecognized

如果你不想让你的用户命令,以便紧密结合实际函数本身,你可以使用一个dict作为一个分支结构(或派遣),而不是有很多的if/elif/else声明:

# Modified main.py 
import commands 

COMMAND_DISPATCH = { 
    'bag': commands.bag, 
    'sack': commands.bag, 
    'other': commands.other, 
    # ... 
} 

# ... 

def user_do(command): 
    action = COMMAND_DISPATCH.get(command, commands.unrecognized) 
    action() 

在本例中,我们不是在commands模块中查找函数,而是在COMMAND_DISPATCH中查找它们。

还有一点建议:不久之后,您会希望将用户输入解析为不止一个命令。对于这个例子,我们假设你想能够接受“command ...”形式的输入。您可以扩展user_input函数来照顾这:

def user_input(): 
    print 'a question' 
    user_input = raw_input('>').split(' ') 
    command = user_input[0] 
    arguments = user_input[1:] 
    return command, arguments 

所以,如果你输入“富酒吧巴兹”,这将返回元组('foo', ['bar', 'baz'])。接下来我们更新主循环来处理参数。

while is_running: 
    # use tuple unpacking to split into command, argument pairs 
    command, arguments = user_input() 
    if command == 'quit': 
     is_running = False 
    else: 
     user_do(command, arguments) 

然后确保我们将它们传递到命令:

def user_do(command, arguments): 
    action = COMMAND_DISPATCH.get(command, commands.unrecognized) 
    action(arguments) 

最后,我们修改命令接受并处理这些参数:

def bag(arguments): 
    for argument in arguments: 
     print 'bagged ', argument 

对于文字冒险,你会想要一个更实质性的解析器,它可以处理command object,command object preposition subject,甚至可能command adjective object ...

+0

我不知道我跟着你。当用户被允许输入(回答问题)时,我需要选择运行命令,而且我不确定如何实现您的建议。 –

+1

我已经添加了一个我的意思的工作示例。但是真的,如果循环构造在这里让你感到困惑,我强烈建议从一些Python教程开始。 –

+0

这不是让我困惑的循环构造,而是用户如何与游戏互动。我的想法包括打印问题,提示用户输入,然后查找关键字并执行不同的模块。如果您不介意在示例中提示和用户输入的工作原理,我将不胜感激。这实际上是一个Python教程,所以我对它很陌生。 –

0

你应该研究“python有限状态机”。它几乎正是你想要的。

什么是状态机?

对状态机的过于精确的描述是它是一个有向图,由一组节点和一组相应的转换函数集合组成。该机器通过响应一系列事件而“运行”。每个事件都位于属于“当前”节点的转换函数 的域中,其中函数的范围是节点的子集 。该函数返回“下一个”(可能是 相同)节点。至少其中一个节点必须是最终状态。当达到 结束状态时,机器停止。

何时使用状态机...

  1. 开始在初始状态。
  2. 阅读一行输入。
  3. 根据输入和当前状态,转换到新状态或根据当前状态处理行。

什么@MatthewTrevor在他的回答提出类似,你将有一个主循环,并通过“国家”语境的第一入口点调用(startintro或其他)。这个调用可以改变状态的上下文来指向别的东西。当控制再次回到主循环并检查状态时,它将运行新状态。

相关问题