简体   繁体   English

如何创建字典并将数据保存到文本文件? (测验游戏python)

[英]How to create a dictionary and save the data to a text file? (Quiz game python)

This is python and I am using idle version 3.4.2. 这是python,我使用的是空闲版本3.4.2。 So at the moment my code works but I would like to adapt it to be able to: Save the most recent three scores for the name (as they re-run the code and the scores are saving in the text file). 因此,目前我的代码可以运行,但我希望对其进行调整,以便能够:为该名称保存最新的三个分数(因为它们重新运行代码,并且分数保存在文本文件中)。 However there is an issue that whatever "name" is entered, it re saves on its own line with the score, rather than "appending" (I know this is because it's not saved in the form of a list/dictionary, but how would I do that? - or I read that you can "split" the line?) 但是,存在一个问题,无论输入什么“名称”,它都会与分数一起保存在自己的行中,而不是“追加”(我知道这是因为它没有以列表/字典的形式保存,但是怎么保存?是吗-或我读到您可以“拆分”线路?)

That is my first question and if anyone can help I would be so hugely appreciative, I am new to python so this is ab ig challenge for me! 这是我的第一个问题,如果有人能帮助我,我将非常感激,我是python的新手,所以这对我来说是个挑战! Any comments or suggestions are very welcome!! 任何意见或建议都非常欢迎!!

import random #import module
print("What is your name?") #prints writing in brackets
name = input().title() #Capitalizes the first letter of the word inputted
print("What class are you in? (Enter 1, 2 or 3)") #asks the user to input a number

while True:
   try:
       class_number = int(input()) #asks for an integer input from user
   except ValueError: 
       print("Sorry, I didn't understand that, please try again") #print statement
       continue

   if class_number > 3: #if input is more than 3
       print("SORRY but that class isn't recognised, try again") #print statement
       continue
   else:
       print ("Hello,", name, "from class", class_number, "welcome to my quiz") #prints writing in brackets and anything saved in the variable "name" and "class_number"
       break #break out of loop

score = 0  #sets the variable "score" to zero
question = 0 # sets the variable "question" to zero

while question < 3:#If questions (intitally set to 0) is smaller than 10, carry out this function
   question +=1 # add one to the value of "question"
   maths = random.randint(1,3) #randomly generate a number from 1-3 and store as "maths"
   num1 = random.randint(1,10)#randomly generate an integer from 1-10 and store as "num1"
   num2 = random.randint(1,10)#randomly generate a second integer from 1-10 and store as "num2"
   if maths == 1: #if the number generated is 1 
       print(num1, "+", num2) #prints num1 + num2
       ans = num1 + num2 #sets "ans" to equal the value of num1 added to num2

   elif maths == 2: #if the number generated is 1
       print(num1, "*", num2) #print num1 multiplied by num2
       ans = num1 * num2 #sets "ans" to equal the value of num1 multiplied by num2

   else: #else run this part of code
       print(num1, "-", num2) #print num1 subtracted by num2
       ans = num1 - num2 #sets "ans" to equal the value of num1 subtracted by num2

   while True:
       try:
           user_ans = int(input()) #user inputs answer to question
       except ValueError: #runs when the user input is no an integer
           print ("SORRY but that answer isn't recognised, try again")
       else:
           break

   if user_ans == ans:
       score+=1
       print("Well done, you are CORRECT")

   else:
       print("SORRY, you are INCORRECT") #print writing in brackets
       print("The correct answer was", ans)

if score == 10: #run this part of code if "score" equals 10
       print("fantastic", name, "you got full marks!") #print statement and name 
elif score >= 6: #run this part of code if "score" is larger than or equal to 6
       print("well done, there's some improvement to be done here though", name, "you got", score, "/10")# then print statement and score
elif score <=5: #run this part of code if "score" is smaller than or equal to 5
       print("hmm, maybe some more practise would be beneficial", name, "you got", score, "/10") #then print statement and score

class_number = str(class_number) + ".txt" #this adds '.txt' to the end of the file (therefore creating a text file) so it can be used to create a file under the name of the class
file = open(class_number, 'a') #opens the file in 'append' mode so you don't delete all the information
file.write(str(name + " : ")) #writes the name and ":" to file
file.write(str(score)) #writes the score to file
file.write('\n')#writes the score to the file
file.close()#safely closes the file to save the information

view = int(input("would you like to view the scores? If yes, press 1 or not press 2"))
if view == 1:
   exit
elif view == 2:
   exit #to be completed

If you want to save the user's score to a list... 如果要将用户的分数保存到列表中...

my_list = []
my_list.append(score)

You may want to read in the file before the game starts as well. 您可能还需要在游戏开始之前读入文件。 Then, you will need to populate the list with scores that are in the text file. 然后,您将需要使用文本文件中的分数填充列表。

with open(class_number) as scorefile:
    for line in scorefile:
        my_list.append(line)

Finally, when the game ends you'll want to add the user's score to the file. 最后,当游戏结束时,您需要将用户的分数添加到文件中。 In this case, I'll keep it simple and not include the person's name for an example, you can still add the line to the list though. 在这种情况下,我将保持简单,并且不包括示例的人名,尽管如此,您仍然可以将行添加到列表中。

f = open(class_number 'w')
f.write("\n" + score)
f.close()

And then if they view the scores, just print off the value of my_list, separating each element in the list by a new line. 然后,如果他们查看分数,只需打印出my_list的值,并用新行将列表中的每个元素分开。

If you want to keep it human readable write it in a json file: 如果要使其易于阅读,请将其写入json文件:

import json

your_dictonary = {"my_key":"one_value"}

str_to_save = json.dumps(your_dictonary)
# Then write it to a file as you did before

Loading is almost as easy: 加载几乎一样容易:

json.loads(file_content) # after you read the file as usual

Use the pickle module to store your data. 使用pickle模块存储数据。 Organise your user => score relation into an dictionary, then call pickle.dump(filename, theDict) to save it to a file. user => score关系组织到字典中,然后调用pickle.dump(filename, theDict)将其保存到文件中。

When you need it back, call theDict = pickle.load(filename) and it will load the data from the pickle file. 当需要它时,调用theDict = pickle.load(filename) ,它将从pickle文件中加载数据。 This approach is better than you having to devise your own parsing algorithm. 这种方法比必须设计自己的解析算法更好。

If you're ok with changing the look of your file, try saving the file as json . 如果可以更改文件的外观,请尝试将文件另存为json

At the top of your code, load in the scores from the file: 在代码的顶部,从文件中加载分数:

import json
with open('{}.txt'.format(class_number)) as f:
    scores = json.load(f)

Then you can modify scores in your dictionary and write back to the file: 然后,您可以在字典中修改分数并写回文件:

scores[name] = score
with open('{}.txt'.format(class_number)) as f:
    json.dump(scores, f)

This code doesn't store more than the latest score, but you can explore options for saving more than one score per name. 该代码存储的最新分数不多,但是您可以探索为每个名称保存多个分数的选项。 I suggest taking a look at defaultdict . 我建议看一下defaultdict

Some answers suggest storing the scores as JSON (good idea) or pickling them (bad idea! it's dangerous ). 一些答案建议将分数存储为JSON(好主意)或腌制(坏主意! 这很危险 )。 This answer assumes you want to keep the flat-file, oldest-first format. 该答案假定您要保留平面文件,最旧优先的格式。

You're opening the file in append mode, so you won't be able to change any of the content. 您将以追加模式打开文件,因此将无法更改任何内容。 To make changes, you'll first need to read from the file: 要进行更改,您首先需要读取文件:

try:
    fileh = open(class_number, 'r')
    oldlines = fileh.readlines()
    fileh.close()
except IOError: # If we didn't find the file, there were no old scores
    oldlines = []

Note that this reads all the lines; 注意,这将读取所有行; if your file grows very large, it won't all fit into memory and you should read line-by-line and write as you go. 如果文件变得非常大,那么它就无法全部放入内存中,您应该逐行阅读并随心所欲地写。

For each line: 对于每一行:

  • If it's another person's score, you have no reason to touch it, just write it back verbatim. 如果是别人的分数,则没有理由去触摸它,只需逐字写回即可。
  • If it's this person's score, keep it iff it's one of the two most recent. 如果这是此人的分数,请保持其为最近的两个分数之一。

It's slightly easier to keep track of the most-recent scores if we start with the most recent line, so let's do that: 如果我们从最新的行开始,跟踪最近的分数会稍微容易一些,所以让我们这样做:

updatedlines = []
recentscores = 0
for line in oldlines[::-1]: # go backwards, most recent line first
    (lname, lscore) = line.split(" : ") # read the name and the score from the line; this will break if the name contains " : "
    if lname == name:
        recentscores += 1 # keep track of how many scores we have for this person
        if recentscores <3:
            updatedlines.append(line)
    else:
            updatedlines.append(line)

updatedlines = updatedlines[::-1] # put the lines back in the right order

Finally, add the new score. 最后,添加新分数。

updatedlines.append("%s : %d\n" % (name, score))

Now we can write the lines back to the file: 现在我们可以将这些行写回到文件中:

fileh = open(class_number, 'w')
fileh.writelines(updatedlines)
fileh.close()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM