1

我一直在完成本书中的练习,但遇到了一些障碍。挑战在于:

“改进 Trivia Challenge 游戏,使其在文件中维护高分列表。程序应记录玩家的姓名和分数。使用腌制对象存储高分。”

我设法将分数保存到列表中,然后将此列表附加到 dat 文件中。但是,当我尝试查看分数/读取文件时,它似乎只显示输入的第一个分数。我查看了 bat 文件,它似乎正确地转储了列表,所以我想知道我是否搞砸了检索部分?

谢谢阅读

这是代码(之前):

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 个元素的列表)。

在添加新值之前,您需要做的是在函数开始时添加一些代码以从文件中加载高分列表。当没有以前的高分文件时,您需要输入一个特殊情况,但是使用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 回答