Create highscore file for simple textgame - python

I'm trying to create a highscore file in Python 3.1 that stores (already declared) username with scores. Then, I want the program to print the top 5 scores and the users that achieved them.
Currently, I'm using two files - highscores.txt and highuser.txt. What I want is for the code to find the highest integer value in highscores.txt, take its array and match it to the same position in highuser.txt.
Here's my current code:
def highscores():
global score
highscores = open("highscores.txt", "a")
highscores.write(str(score))
highscores.write("\n")
print("done")
highscoreuser = open("highuser.txt", "a")
global username
highscoreuser.write(username)
highscoreuser.write("\n")
print("done")
This code works, but I don't know how to sort the files.

this should do it
with open('highscores.txt','r') as infile:
maxval = 0
maxline = None
i = 0
for line in infile:
if maxval<int(line):
maxline = i
maxval = int(line)
i+=1
i = 0
with open('highuser.txt','r') as infile:
for line in infile:
if i == maxline:
highuser = line.strip()
break
i+=1

Try this:
https://www.geeksforgeeks.org/python-program-to-find-n-largest-elements-from-a-list/
Just use it for 5.
Also make sure to close your files. highscores.close()
And reopen them to read. highscores = highscores.open("highscores.txt", "r")
Make an array of all highscores by .split("\n")
Then similarly create a array of all users by .split("\n")
For each of the top 5 scores search the array for that score and get the indexes.
Then plug in those indexes into the user array and get the resulting users.
You could also make a dictionary with each user and their score and just find the 5 highest scores from all the users.

Related

[may be duplicate) How to read a number from a file and use it as a variable?

I'm new to python so this is most likely basic knowledge, but how do I read a number from a text file and use it as a variable? I'm trying to make a game where it counts your points and saves it to a plain text file, and when you first run the game it checks for that file and reads the points from your last session. I tried this but it didnt work:
for saving:
def save():
with open('gameSave.txt', 'w') as f:
for points in points:
f.write('%d' % points)
for loading:
with open("gameSave.txt", "r", encoding="utf-8") as g:
points = g.readlines()
can anyone help? The points just need to be loaded and save as an integer but i can't figure out how.
Write two discrete functions. One to save accumulated points and the other to retrieve what may have previously been saved. Something like this:
FILENAME = 'gameSave.txt'
def getSavedPoints():
try:
with open(FILENAME) as data:
return int(data.read())
except FileNotFoundError:
return 0
def savePoints(points):
with open(FILENAME, 'w') as data:
data.write(str(points))
points = getSavedPoints()
# play game and accumulate points
points += 100
savePoints(points)
print(getSavedPoints())
So let's assume that no points have previously been saved then the output from this would be:
100
Store one number only
points = 200
# Store points
f = open("points.txt", "w")
f.write(str(points))
f.close()
# Retrieve them now
f = open("points.txt", "r")
points = int(f.read())
Cheers

Fix compared data and return line number and data

I have typed a program to compare vehicle A price (v_priceA) to various other vehicle prices in a carprices.txt text file which are in a new line.
The result should be a new text called highprices.txt file with all the prices greater than the price of Vehicle A in a newline and the associated line number from carprices.txt
My problem is am able to generate two text files that has the line number of the greater file and another with the greater price, instead of the greater price itself and line number together. I need to fix this.
Vehicle A price: 2500.50
v_priceA = 2500.50
a_file = 'carprices.txt'
with open(a_file, 'r') as document:
values = [x for x, value in enumerate(document) if float(value) > v_priceA]
new_file = open('highpriceposition.txt', 'w')
for x in values:
new_file.write(str(x) + '\n')
new_file.close()
a_file = 'carprices.txt'
with open(a_file, 'r') as document:
values = [value for value in document if float(value) > v_priceA]
with open('highprice.txt', 'w') as f:
for x in values:
f.write(str(x)+'\n')
positionprice.txt
2 2900.00
3 3500.50
5 25000.30
6 45000.50
When you write to the new file new_file.write() you need to pass it both the line number and price. I.E.
v_priceA = 2500.50
a_file = 'carprices.txt'
output_file = 'highprices.txt'
with open(a_file, 'r') as document:
with open(output_file, 'w') as new_file:
for line, price in enumerate(document):
if float(price) > v_priceA:
new_file.write(str(line) + " " + str(price))
# See how I pass both in here?
It's important to know that whenever you open() a file in python as write "w" it's going to erase whatever is in that file before writing to it. (There's an append option if your interested).
Docs for Open.
Notice how I only open the output file once in the above code? That should help.
Now on to how enumerate works. It takes an iterable object in python
and for each item in that iterable returns a tuple of (itemIndex, item) with at least one very important exception it basically the succinct equivalent of:
def myEnumerate(iterableParameter):
i = 0
outPutList = []
while i < len(iterableParameter):
outPutList += (i, iterableParameter[i])
return outPutList
The important exception is that enumerate creates a generator where as the above creates a list. See further reading.

Can't read numbers from a text file in python

I have to read a list of 12 grades from a text file. Each grade is on a new line in the text file. I have to find the lowest grade and drop it(in the text file as well), then find the average score of the grades. I am having trouble making the text values into integer values so I can find the average. I also can't figure out how to find the lowest grade and drop it.
Here is my code:
try:
homeworkFile = open('homework.txt', 'r')
except:
print("Error: invalid file")
else:
lines = homeworkFile.readlines()
homeworkFile.close()
homeworkFile = open('homework.txt', 'w')
for line in lines:
Thanks for any help you can give!
So this is just one way to take all of your values and calculate the average.
input_file = input("enter file name: ")
open_file = open(input_file, 'r')
Here I just put all of your values into notepad and read through it
grades_list = []
for grade in open_file:
grade_format = grade.strip() #how to remove extra blank space
grades_list.append(grade_format)
Then I used a for-loop to go through each line and put the grades into a list
grade_convert = [] #new list for all of the converted values
for grade in grades_list:
convert = float(grade) #convert each value in the list into a float
grade_convert.append(convert)
I used another list for converted each value
grade_convert = sorted(grade_convert) #very first element will be the lowest
grade_convert.pop(0) #permanently removes the very first item
grade_total = 0 #set a counter
for grade in grade_convert:
grade_total += grade #add all of the values to the counter
grade_average = grade_total / len(grade_convert) #len is number of items
print(grade_average)
grades_list = []
for line in lines :`
grade = float(line)
grades_list.append(grade)
grades_list.sort()
lowest_grade = grades_list[0] #There is the lowest grade
This is one way you can structure your logic. You need to convert values to float pre-processing. Using with is recommended instead of using open and close explicitly.
import os
file = 'homework.txt'
# check if file exists
assert os.path.exists(file), "File does not exist: {0}".format(file)
# use with to open/close file implicitly
with open(mystr, 'w') as file_in:
lines = homeworkFile.readlines()
grades = sorted(float(line) for line in lines)
# drop lowest trade
del grades[0]

Replacing data in files with new inputs

First of all my program must work with several files and 10 inputs in every file, this is just little piece, to be clear.
My code right now:
code = input(">> ")
print("\nPress <Enter> and parameter will be same!")
f = open("komad_namestaja.txt", "r")
allDATA = f.readlines()
f.close()
for line in allDATA:
lst = line.split("|")
if code == lst[0]:
print("\nName :", lst[1])
name = input("New Name >> ")
if name == "":
name = lst[1]
f = open("komad_namestaja.txt", "r")
allDATA = f.read()
f.close()
newdata = allDATA.replace(lst[1], name)
f = open("komad_namestaja.txt", "w")
f.write(newdata)
f.close()
print("\ndestination :", lst[2])
destination = input("New destination >> ")
if destination == "":
destination = lst[2]
#Writting function here
File before:
312|chessburger|Denmark
621|chesscake|USA
code input: 312
name input: Gyros
destination input: Poland
file after inputs:
312|Gyros|Poland
621|chesscake|USA
Problem is this replacing in file I cant write 7 lines code every time, because I have 10 x 5 inputs, and also I tried everything and cant make function of this.
I must write some function for reading/writing/replacing or replacing all inputs after last one.
You don't have to read the file in every time to modify one field, write it out, reopen it to change another field, and so on. That's inefficient, and in your case, causes code explosion.
Since your files are small, you could just read everything into memory at once and work on it in memory. Your code is easy to map via a dict.
Here's a function that takes a filename and converts your file into a dictionary.
def create_mapping(filename):
with open(filename, 'r') as infile:
data = infile.readlines()
mapping = {int(k): (i,d) for k,i,d in
(x.strip().split('|') for x in data)}
# Your mapping now looks like
# { 312: ('cheeseburger', 'Denmark'),
# 621: ('chesscake', 'USA') }
return mapping
Then you can update the mapping from user input since it's just a dictionary.
Once you want to write the file out, you can just serialize out your dictionary by iterating over the keys and rejoining all the elements using |.
If you want to use lists
If you want to stick with just using lists for everything, that is possible.
I would still recommend reading your file into a list, like so:
def load_file(filename):
with open(filename, 'r') as infile:
data = infile.readlines()
items = [(int(k), i, d) for k,i,d in
(x.strip().split('|') for x in data]
# Your list now looks like
# [(312, 'cheeseburger', 'Denmark'), (621, 'chesscake', 'USA')]
return items
Then when you get some user input, you have to traverse the list and find the tuple with what you want inside.
For example, say the user entered code 312, you could find the tuple that contained the 312 value from the list of tuples with this:
items = load_file(filename)
# Get input for 'code' from user
code = int(input(">> "))
# Get the position in the list where the item with this code is
try:
list_position = [item[0] for item in items].index(code)
# Do whatever you need to (ask for more input?)
# If you have to overwrite the element, just reassign its
# position in the list with
# items[list_position] = (code, blah, blah)
except IndexError:
# This means that the user's entered code wasn't entered
# Here you do what you need to (maybe add a new item to the list),
# but I'm just going to pass
pass

Python for the absolute beginner, Chapter 7 challenge 2

I've been going through the exercises in this book and I've hit a bit of a road block. The challenge is to:
"Improve the Trivia Challenge game so that it maintains a high-scores list in a file. The program should record the player's name and score. Store the high scores using a pickled object."
I've managed to save scores to a list and then append this list to a dat file. However, when I try to view the scores/read the file it only seems to show the first score entered. I took a look at the bat file and it seems to be dumping the list correctly, so I'm wondering if I'm messing up the retrieval part?
Thanks for reading
Here's the code (BEFORE):
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.")
Solution(AFTER):
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)
f = open("pickles1.dat", "ab")
# ^
You have opened the file in "append" mode. That's fine, but it's probably not doing what you want. each time you try to save data to such a file, it is tacked on the end. You'd have to read every single item you ever wrote to get to the most recently written. instead, open the file in write mode. This way, its contents will be replaced every time:
f = open("pickles1.dat", "wb")
alternatively, you can use appending, but you'll have to call pickle.load() repeatedly to see all of the written values. Here's pseudocode, first for the former, with "w"
scores = pickle.load(open('scores.dat', 'rb'))
scores.append(123)
pickle.dump(scores, open('scores.dat', 'wb'))
and the latter:
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
I hope you can see why I think the former (overwriting) is nicer; it's much simpler.
There are a few problems with your code. #TokenMacGuy has identified one, which is that you're appending your results onto the end of the output file, rather than overwriting the previous values.
There is a more fundamental issue though. When you run the highscores function, you are always starting with an empty high score list. You then add a single score to it, and write it out. With this structure, you will never have more than one score being written at a time (and so even if you get it to read back what you've written properly, it will only get a 1-element list).
What you need to do is add some code to load the high score list from your file at the start of the function, before you add the new value. You need to put in a special case for when there is no previous high score file, but that's not too dificult with a try/except block. Here's some abbreviated code:
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
A benefit to this approach is that you don't need to reread the file later if the user asks for it, since the high_scores list will be up to date already.

Categories

Resources