1

私はこの本にある演習を行ってきましたが、ちょっとした障害にぶつかりました。課題は次のとおりです。

「トリビア チャレンジ ゲームを改善して、ハイスコアのリストをファイルに保持できるようにします。プログラムは、プレイヤーの名前とスコアを記録する必要があります。ハイスコアは、ピクルス オブジェクトを使用して保存します。」

スコアをリストに保存し、このリストを dat ファイルに追加することができました。ただし、スコアを表示したりファイルを読み取ろうとすると、最初に入力したスコアしか表示されないようです。バットファイルを見てみたところ、正しくリストをダンプしているように見えるので、取得部分をめちゃくちゃにしているのではないでしょうか?

読んでくれてありがとう

コードは次のとおりです(BEFORE):

def high_score():
    """Records a player's score"""
    high_scores = []

    #add a score
    name = input("What is your name? ")
    player_score = int(input("What is your score? "))
    entry = (name, player_score)
    high_scores.append(entry)
    high_scores.sort(reverse=True)
    high_scores = high_scores[:5]       # keep only top five

    # Open a new file to store the pickled list
    f = open("pickles1.dat", "ab")
    pickle.dump(high_scores, f)
    f.close()

    choice = None
    while choice !="0":
        print(
            """
            0 - Quit
            1 - Show high scores
            """
            )
        choice = input("choice: ")
        print()

        # exit
        if choice == "0":
            print("Goodbye")

        # show a score
        if choice == "1":
            f = open("pickles1.dat", "rb")
            show_scores = pickle.load(f)
            print(show_scores)
            f.close()

    input("\n\nPress enter to exit.")

ソリューション (後):

def high_score():
"""Records a player's score"""

# no previous high score file
try:
    with open("pickles1.dat", "rb") as f:
        high_scores = pickle.load(f)
except EOFError:
    high_scores = []

#add a score // Do current stuff for adding a new score...
name = input("What is your name? ")
player_score = int(input("What is your score? "))
entry = (name, player_score)
high_scores.append(entry)
high_scores.sort(reverse=True)
high_scores = high_scores[:5]       # keep only top five

# dump scores
with open("pickles1.dat", "wb") as f:
    pickle.dump(high_scores, f)
4

2 に答える 2

2
f = open("pickles1.dat", "ab")
#                         ^

ファイルを「追加」モードで開いています。それは問題ありませんが、おそらくあなたが望むことをしていません。このようなファイルにデータを保存しようとするたびに、最後に追加されます。最近書いたものにたどり着くには、これまでに書いたすべての項目を読まなければなりません。代わりに、書き込みモードでファイルを開きます。このように、その内容は毎回置き換えられます。

f = open("pickles1.dat", "wb")

または、追加を使用することもできますがpickle.load()、書き込まれた値をすべて表示するには、繰り返し呼び出す必要があります。最初に前者の疑似コードを次に示します。"w"

scores = pickle.load(open('scores.dat', 'rb'))
scores.append(123)
pickle.dump(scores, open('scores.dat', 'wb'))

そして後者:

pickle.dump(123, open('scores.dat', 'ab'))
scores = []
with open('scores.dat', 'rb') as f:
    while True:
        try:
            scores.append(pickle.load(f))
        except EOFError:
            break

前者 (上書き) の方が優れていると私が考える理由を理解していただければ幸いです。それははるかに簡単です。

于 2013-07-31T12:33:53.280 に答える
1

コードにはいくつかの問題があります。@TokenMacGuy は、以前の値を上書きするのではなく、結果を出力ファイルの最後に追加していることを特定しました。

しかし、もっと根本的な問題があります。関数を実行するhighscoresと、常に空のハイスコア リストから開始されます。次に、スコアを 1 つ追加して書き出します。この構造では、一度に複数のスコアが書き込まれることはありません (そのため、書き込んだものを正しく読み取ったとしても、1 つの要素のリストしか得られません)。

新しい値を追加する前に、関数の開始時にファイルからハイスコア リストをロードするコードを追加する必要があります。以前のハイスコアファイルがない場合は特別なケースを入れる必要がありますが、try/exceptブロックでそれほど難しくありません。短縮されたコードを次に示します。

def high_score():
    try:
        with open("pickles1.dat", "rb") as f:
            high_scores = pickle.load(f)
    except FileNotFoundError:
        high_scores = []

    # do current stuff for adding a new score, sorting and slicing

    with open("pickles1.dat", "wb") as f: # "wb" mode overwrites the previous file
        pickle.dump(high_scores, f)

    # do other stuff, like displaying high_scores

high_scoresこのアプローチの利点は、リストがすでに最新であるため、ユーザーが要求した場合に後でファイルを再読み込みする必要がないことです。

于 2013-07-31T12:50:53.977 に答える