简体   繁体   中英

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. 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! 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.

If you want to keep it human readable write it in a json file:

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. Organise your user => score relation into an dictionary, then call pickle.dump(filename, theDict) to save it to a file.

When you need it back, call theDict = pickle.load(filename) and it will load the data from the pickle file. 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 .

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 .

Some answers suggest storing the scores as JSON (good idea) or pickling them (bad idea! it's dangerous ). 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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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