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"

問題は、ユーザーが中断したところに戻ることです。

4

2 に答える 2

2

必要なのは、メインのゲーム ループです。

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

これにより、ループ内の 3 行のコードが is である限り繰り返され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_dogetattr呼び出しはユーザーが入力した文字列をcommandモジュールの内容と比較し、存在する場合は同じ名前の関数を返し、存在unrecognizedしない場合はフォールバック関数を返します。actionコマンド関数または のいずれかを保持しますunrecognized

ユーザーコマンドを実際の関数自体に強く結び付けたくない場合は、多くのステートメントを使用する代わりに、dicta を分岐構造 (またはdispatch ) として使用できます。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代わりにそれらを検索します。

もう 1 つアドバイスがあります。すぐに、ユーザー入力を 1 つのコマンド以上に解析する方法を検討したくなるでしょう。この例では、「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」と入力すると、tuple が返され('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 objectcommand object preposition subject、 、場合によってはcommand adjective object ....

于 2012-09-12T02:40:03.913 に答える
0

「python有限状態機械」を研究する必要があります。それはまさにあなたが望むものです。

ステートマシンとは?

ステート マシンの過度に正確な説明は、一連のノードと対応する一連の遷移関数で構成される有向グラフであるということです。マシンは、一連のイベントに応答することで「実行」されます。各イベントは、「現在の」ノードに属する遷移関数のドメインにあり、関数の範囲はノードのサブセットです。この関数は、「次の」(おそらく同じ) ノードを返します。これらのノードの少なくとも 1 つが終了状態である必要があります。終了状態に達すると、マシンは停止します。

ステート マシンを使用する場合 ...

  1. 初期状態からスタート。
  2. 入力行を読み取ります。
  3. 入力と現在の状態に応じて、新しい状態に遷移するか、現在の状態に応じてラインを処理します。

@MatthewTrevorが彼の回答で提案したのと同様に、メインループがあり、「状態」コンテキストを最初のエントリポイント呼び出し(startまたはintroその他)に渡します。その呼び出しは、状態コンテキストを別のものを指すように変更できます。制御が再びメイン ループに戻り、状態をチェックすると、新しい状態が実行されます。

于 2012-09-12T16:55:32.623 に答える