0

私は、主な機能が3つのパラメーターを受け入れる、自分で選択する冒険プロジェクトに取り組んでいます。

  • 最初のパラメーターは、関数によって出力されます。これは常に、シナリオを説明するテキストを含む変数です
  • 2 番目のパラメーターは常に、関数によって出力される現在のシナリオに関連する選択肢を含む変数です。
  • 3 番目のパラメーターは、キーがシナリオの選択に対応し、ユーザーの入力と比較される辞書です。キーの値には、次の 3 つの引数が含まれます。

例。

text1 = 'This is the scenario'  
text2 = 'These are the choices'

dict2 = {'1':[text2, text1, dict1]}
dict1 = {'1':[text1, text2, dict2]}

def mainloop(scenario, choice, consequence):
    print scenario
    print choice

    answer = raw_input('Please input 1, 2 or 3>>> ')

    if answer in consequence.keys():
        mainloop(*consequence[answer])

mainloop(text3, text2, dict1)   

これは私のプロジェクトを設計するための良い方法だと思いましたが、ディクショナリ パラメータで問題が発生しています。辞書の値には、他の辞書を含む引数のリストが含まれているため、エラーが発生し続けます。

NameError: name 'dict1' is not defined

辞書を定義する順序をフリップフロップすると、同じエラーが発生すると予想されますが、「dict2」が定義されていないだけです。このコンセプトを機能させる方法について何かアドバイスはありますか? それとも、まったく異なるアプローチを取る時が来ましたか?

4

4 に答える 4

3

2 つの dict が必要な理由はよくわかりませんが、そうすると仮定すると、循環参照を使用して dict を定義することができます。

text1 = 'This is the scenario'  
text2 = 'These are the choices'

dict1, dict2 = {}, {}
dict2['1'] = [text2, text1, dict1]
dict1['1'] = [text1, text2, dict2]
于 2013-11-13T18:14:19.913 に答える
1

アプローチ全体について再考することをお勧めすることがいくつかあります。

他の人が指摘したように、mainloop()実際にはループではありません。それは再帰関数です。理想的には、これがゲーム ループである場合は、次のようにする必要があります。</p>

def myGameLoop():
    gameRunning = True
    while gameRunning:
        # code that displays your rooms, gets user input,
        #and checks to make sure that gameRunning is not False.
        #for an example, something like:
        if somethingAwfulHappened
            gameRunning = False

このように、 をmainloop複数回呼び出す必要はなく、それ自体を呼び出す理由はありません。

さらに、あなたの部屋のディクテーション/リストが存在しないことを伝え続ける理由は、まあ、そうではないからです:) これは実際、あなたの懸念を分離することが良い考えである理由のかなり良い例です!

このように考えてみてください: なぜ「部屋」オブジェクトは、辞書、リスト、オブジェクトなどであるかにかかわらず、他の部屋に関するデータを含む必要があるのでしょうか? 確かに、あなたのキッチンはバスルームに通じているかもしれませんが、あなたのキッチンはそれがバスルームにつながっていることを知っていますか? あなたの寝室の代わりにバスルームにつながることで、それは新しい目的を果たしますか? キッチンがバスルームに接続されていることを「気に」しないのと同じように、ディクテーションは、独自のデータで明示的に相互に名前を付けることによって接続されていることを「知る」必要もありません。

代わりに、すべての部屋を定義してから、部屋間の関係を説明する「マップ」を作成するのが理想的なアプローチかもしれません。たとえば、次のようになります。

kitchen = {
    "name":"Kitchen",
    "description": "This is the kitchen! It's nice and clean.",
    "exits": "S", "E"
}

bathroom = {
    "name":"Bathroom",
    "description":"This is the bathroom. Someone left a towel on the floor.",
    "exits":"W", "S"
}
#and so on, creating rooms

次に、このすべての情報を保持し、それらの出口がどのように機能するかを説明するマップ dict を作成します。

mapOfHouse = {
    "kitchen": kitchen,
    "leadsTo": {
        "S": bathroom,
        "E": someOtherRoom ##some other place you've defined
    },
    "bathroom": bathroom,
    "leadsTo": {
        "S": otherAwesomePlaces,
        "E": kitchen
    },

    #and so on for other rooms in the house/on the map/etc
 }

これをすべてスケッチしたら、プレイヤーの入力を取得するようにゲームループを設定し、部屋の出口と照合し、一致する場合は、ループがまだ残っTrueている限り、上部に戻り、更新された情報を表示します.

より多くの作業のように見えますが、実際には、これにより膨大な量の自由が得られます。部屋を設計するときは厳密に部屋に集中し、マップを更新するときは厳密にマップに集中することができます。その後、ループしている内容をあまり気にしないゲームループを設計できます。それはTrueずっととどまり、プレイヤーから良い指示を得るからです。

于 2013-11-13T18:44:45.490 に答える
0

あなたの問題は次のとおりです。

dict2 = {'1':[text2, text1, dict1]} # NameError: Here dict1 does not exist yet
dict1 = {'1':[text1, text2, dict2]}

オブジェクトを参照する前にオブジェクトを定義することによってのみ、これを解決できます。それを達成するために、次のようにすることができます。

dict1, dict2 = {}, {} # Define both objects
dict1[1] = [text2, text1, dict2] # Here dict2 is already defined, no NameError
dict1[2] = None # ...
dict2[1] = [text1, text2, dict1] # And here is dict1 already defined too
dict2[2] = None # ...

私たちが尋ねることができる質問は、オブジェクトを参照し、後でそれを変更すると、参照が変更されるか?ということです。 答えはイエスです。コピーではなく参照を使用している場合 (辞書を割り当てると、常にそれらが参照されます)。

参照ではなく、コピーを作成したい場合はどうしますか?

deepcopyモジュールのandcopy関数を介してそれを行うことができcopyます。

NameErrorsの問題は、そのような名前が定義されていないことです。Python は名前を使用して変数を追跡しません。同じ名前が (異なるスコープ内または異なる時間で) 異なる変数に対応することができ、同じ変数が異なる名前を介してアクセスされる可能性があります (ある名前の値を別の名前に割り当てることによって)。

を実行すると、変数とその名前のリンクdel xが解除されますが、常にオブジェクトが削除されるわけではありません。

たとえば、次のコードは機能し、stash正しく出力されますが、演算子を介してオブジェクトをそれを含むオブジェクトからdelリンク解除しました。str'hello'x

x = {1: 'hello'}
stash = x[1]
del x[1]

print stash

stashオブジェクトも削除すると、オブジェクト'hello'はある時点でガベージコレクションされる傾向があります。

リマインダー

名前を使用して他のオブジェクトを参照する場合は、その参照が発生する前に名前を付ける必要があります。

于 2013-11-13T18:33:13.217 に答える