2012-09-12 75 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或其他)。這個調用可以改變狀態的上下文來指向別的東西。當控制再次回到主循環並檢查狀態時,它將運行新狀態。

相關問題