我遇到一个问题,即函数只会覆盖.txt文件中已存在的行。当游戏退出时,该函数应该为文件写一个高分(我通过跟随youtube教程制作了一个蛇游戏)。我无法弄清楚为什么它不会开始新的生产线,任何人都可以解释它背后的逻辑,以及我如何解决它?我读到的地方不是" w"在f.open()中,我应该键入" rb"或者其他的东西。因为我对这个"写到文件"有点新意。好事,我觉得很难。
另外,我想在文件中将高分从最高到最低排序(换句话说,将finalScore从最高到最低排序)。我不知道我应该如何继续编码,所以我会提供一些帮助。你看,我想把当前的高分打印到控制台(为了得分)
下面是代码:
import random
import time
name = "Andreas"
finalScore = random.randint(1,10)
def scoreToFile(finalScore):
#Has to be generated here, since we need the exact current time
currentTime = time.strftime("%c")
print("Sucsessfully logged score (finalScore) to highscores.txt")
f = open("highscores.txt", "w")
#fileOutput = [(currentTime, ":", name, "-", finalScore)]
fileOutput = [(finalScore, "-", name, currentTime)]
for t in fileOutput:
line = ' '.join(str(x) for x in t)
f.write(line + "\n")
f.close()
scoreToFile(finalScore)
无论如何,圣诞快乐我的同伴蟒蛇极客们! :d
答案 0 :(得分:3)
1)一个选项是以追加模式打开文件。 替换:
f = open("highscores.txt", "w")
使用:
f = open("highscores.txt", "a")
2)另一个选择是替换这个块,
f = open("highscores.txt", "w")
#fileOutput = [(currentTime, ":", name, "-", finalScore)]
fileOutput = [(finalScore, "-", name, currentTime)]
for t in fileOutput:
line = ' '.join(str(x) for x in t)
myfile.write(line + "\n")
f.close()
并使用带风格的
with open("highscores.txt", "a") as myfile:
#fileOutput = [(currentTime, ":", name, "-", finalScore)]
fileOutput = [(finalScore, "-", name, currentTime)]
for t in fileOutput:
line = ' '.join(str(x) for x in t)
myfile.write(line + "\n")
我更喜欢第二种风格,因为它更安全,更干净。
答案 1 :(得分:2)
模式w
会覆盖现有文件;模式'a'追加。此外,处理文件的最佳方式通常是使用with
语句,以确保代表您结束;这样:
fileOutput = [(finalScore, "-", name, currentTime)]
with open("highscores.txt", "a") as f:
for t in fileOutput:
line = ' '.join(str(x) for x in t)
f.write(line + "\n")
对于排序,您需要能够从一行中提取最终得分作为数字:
def minus_score(line):
return -int(line.split()[0])
然后总工作将完成:
def sorted_by_score():
with open("highscores.txt", "r") as f:
result = list(f)
return sorted(result, key=minus_score)
这将为您提供按分数升序排序的列表行(后者是score
否定数字的原因,尽管也可以选择让它返回数字并反转排序),你循环并进一步处理。
补充:所以关于OP的请求,这里是整个程序可能是怎样的(假设存在一个游戏并且返回玩家名称和最终得分的函数,或者当没有更多游戏时返回None
要播放,节目必须退出)。
import time
def play_game():
""" play a game and return name, finalscore;
return None to mean no more games, program finished.
THIS function you'd better code yourself!-)
"""
def scoreToFile(name, finalScore):
""" Add a name and score to the high-scores file. """
currentTime = time.strftime("%c")
fileOutput = finalScore, "-", name, currentTime
line = ' '.join(str(x) for x in fileOutput)
with open("highscores.txt", "a") as f:
f.write(line + "\n")
def minus_score(line):
""" just for sorting purposes, not called directly. """
return -int(line.split()[0])
def sorted_by_score():
""" return list of score lines sorted in descending order of score. """
with open("highscores.txt", "r") as f:
return sorted(f, key=minus_score)
def main():
while True:
game_result = play_game()
if game_result is None: break
scoreToFile(*game_result)
for line in sorted_by_score:
print(line.strip())
答案 2 :(得分:1)
正如其他人所提到的那样,问题是你没有在附加模式下打开文件,所以它每次都会覆盖它而不是添加它。
但是,如果您还想将文件中的数据保持排序,则每次都要覆盖它,因为其内容的顺序可能会随着添加而改变。要做到这一点,首先需要读取内容,更新数据,然后将其写回。
这是您的功能的修改版本。我还更改了文件中的数据如何存储到所谓的Comma (or Character) Separated Values (CSV)格式,因为Python包含一个csv
模块,这使得它可以非常容易地读取,写入以及使用这些文件执行其他操作。
import csv
import random
import time
highscores_filename = "highscores.txt"
HighScoresFirst = True # Determines sort order of data in file
def scoreToFile(name, finalScore):
currentTime = time.strftime("%c")
# Try reading scores from existing file.
try:
with open(highscores_filename, "r", newline='') as csvfile:
highscores = [row for row in csv.reader(csvfile, delimiter='-')]
except FileNotFoundError:
highscores = []
# Add this score to the end of the list.
highscores.append([str(finalScore), name, currentTime])
# Sort updated list by numeric score.
highscores.sort(key=lambda item: int(item[0]), reverse=HighScoresFirst)
# Create/rewrite highscores file from highscores list.
with open(highscores_filename, "w", newline='') as csvfile:
writer = csv.writer(csvfile, delimiter='-')
writer.writerows(highscores)
print("successfully logged score (finalScore) to highscores.txt")
# Simulate using the function several times.
name = "Name"
for i in range(1, 4):
finalScore = random.randint(1,10)
scoreToFile(name + str(i), finalScore)
time.sleep(random.randint(1,3)) # Pause so time values will vary.