2014-12-25 11 views
1

У меня проблема, когда функция просто перезаписывает строку, которая уже существует в TXT-файле. Предполагается, что функция должна записывать рекорды в файл, когда игра завершается (я сделал игру змеи, следуя учебнику по youtube). Я не могу понять, почему он не начнется по новой линии, может кто-нибудь объяснить логику этого и как я это исправлю? Я где-то читал, что вместо «w» в f.open() я должен ввести «rb» или что-то еще. Поскольку я немного новичок в этой «записи в файл», мне сложно.Пишите в файл python - Проблема с линией ( n)

Кроме того, я хочу сортировать рекорды от наивысшего до самого низкого в файле (другими словами, сортировать finalScore от самого высокого до самого низкого). Я понятия не имею, как я должен продолжать и кодировать это, поэтому я бы воспользовался некоторой помощью. Видите ли, я хочу, чтобы распечатать текущие рекордами на консоль (для того, чтобы сделать scoreboad)

Heres код:

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

Do 'f = open (" highscores.txt ", 'a')'. Обратите внимание на флаг '' ', что означает« добавить », а не« перезаписать »] (http://stackoverflow.com/q/1466000/198633). – inspectorG4dget

ответ

2

Режим w перезаписывает существующий файл; mode '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()) 
+0

Я не совсем понимаю ... Где в коде я должен вызвать функции и 'line' в' minus_score' так же, как в функции scoreToFile? Не могли бы вы просто вставить весь код здесь? Спасибо за подробный ответ anywyas! :) – ApeBapsen

+0

Что касается ** когда ** вы должны называть 'sorted_by_score': вы только сказали« Я хочу сортировать рекорды »- так **, когда ** вы называете это, именно тогда, когда вы хотите получить« рекорды », сортировать (циклически, печатать некоторые на консоли или что угодно). Вы никогда не говорите **, когда ** вы хотите сортировать их, и я не могу читать ваши мысли, поэтому я не могу сказать **, когда ** называть 'sorted_by_score' - два« когда »являются одним и то же самое - будь то сразу после 'scoreToFile', или в конце, или когда-либо. Вы никогда не называете 'minus_score' напрямую; встроенный 'sorted' вызывает это ** для **, чтобы произвести сортировку, которую вы желаете. –

+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") 

Я предпочитаю второй стиль s более безопасно и чисто.

+0

Сладкий! Благодаря! Теперь мне нужно выяснить, как сортировать оценки: < – ApeBapsen

+0

@AndreasAmundsen - для сортировки, см. Мой ответ ... –

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. 
+0

Большое спасибо! – ApeBapsen