highscores list

S

Shawn Minisall

I'm writing a game that uses two functions to check and see if a file
called highScoresList.txt exists in the main dir of the game program.
If it doesn, it creates one. That part is working fine. The problem is
arising when it goes to read in the high scores from the file when I
play again.

This is the error msg python is giving me

Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
main()
File "I:\PYTHON\PROJECT #3\PROJECT3.PYW", line 330, in main
if(hasHighScore(wins) == True):
File "I:\PYTHON\PROJECT #3\PROJECT3.PYW", line 175, in hasHighScore
scores,names = string.split(line,"\t")
ValueError: need more than 1 value to unpack

Here's the relavant code:

def hasHighScore(score):
#opens highScoresList.txt
infile = open("highScoresList.txt",'r')
scores = [0,0,0]
names = ["","",""]

#reads in scores from highScoresList.txt
i=0
for line in infile.readlines():
scores,names = string.split(line,"\t")
names=string.rstrip(names)
i += 1
infile.close()

#compares player's score with those in highScoresList.txt
i=0
for i in range(0,len(scores)):
if(score > int(scores)):
return True
else:
return False



def setHighScores(score,name):
#opens highScoresList.txt
infile = open("highScoresList.txt",'r')
scores = [0,0,0]
names = ["","",""]

#reads in scores from highScoresList.txt
i=0
for line in infile.readlines():
scores,names = string.split(line,"\t")
scores=int(scores)
names=string.rstrip(names)
i += 1
infile.close()

#shuffles thru the highScoresList.txt and inserts player's score if
higher then those in file
i=len(scores)
while(score > scores[i-1] and i>0):
i -= 1

scores.insert(i,score)
names.insert(i,name)
scores.pop(len(scores)-1)
names.pop(len(names)-1)

#writes new highScoresList.txt
outfile = open("highScoresList.txt","w")

outfile.write (" High Score Name \n")
outfile.write ("-------------------------------------------------\n")

i=0
for i in range(0,len(scores)):
outfile.write("\t" + str(scores) + "\t\t\t" + names + "\n")
outfile.close()

And here's the call to the functions at the end of my game, included in
the error msg.

#adds player's score to high score list if high enough
if(hasHighScore(wins) == True):
setHighScores(wins,getName(wins))

And this is what the text file looks like when it happens.

High Score Name
-------------------------------------------------
15 SHAWN
0
0

The answer is probably simple, I've just been working on this program so
long that my brain has turned to mush. Any help would be much
appreciated...thanks.
 
Z

Zepo Len

I'm writing a game that uses two functions to check and see if a file
called highScoresList.txt exists in the main dir of the game program.
If it doesn, it creates one. That part is working fine. The problem is
arising when it goes to read in the high scores from the file when I
play again.

This is the error msg python is giving me

Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
main()
File "I:\PYTHON\PROJECT #3\PROJECT3.PYW", line 330, in main
if(hasHighScore(wins) == True):
File "I:\PYTHON\PROJECT #3\PROJECT3.PYW", line 175, in hasHighScore
scores,names = string.split(line,"\t")
ValueError: need more than 1 value to unpack

for line in infile.readlines():
scores,names = string.split(line,"\t")


The error message is straightforward, you are trying to unpack a 1 value
tuple to 2 values

The reason it's a one value tuple is that your first line is this:
outfile.write (" High Score Name \n")

Running split('\t') on this will return a tuple of length one (since there
is no tab in that line)

Your code is also really unpythonic, take a look at this rewrite to see
what you could have done better:

def getHighScoreList():
scores = []
try:
highscore_file = list(open("highScoresList.txt"))
for line in highscore_file[2:]:
score, name = line.split('\t\t\t')
scores.append((int(score), name.rstrip()))
except IOError: # no highscore file yet
pass
return scores

def hasHighScore(score):
scores = [s for (s, n) in getHighScoreList()]
if scores:
return score > min(scores)
return True

def setHighScores(newscore, newname):
max_scores = 3
scores = getHighScoreList()

for i, (score, name) in enumerate(scores):
if newscore > score:
scores.insert(i, (newscore, newname))
break
else:
scores.append((newscore, newname))

outfile = open("highScoresList.txt","w")
outfile.write (" High Score Name \n")
outfile.write ("-------------------------------------------------\n")
for i in range(max_scores):
try:
score, name = scores
except IndexError:
score, name = 0, ''
outfile.write("\t%s\t\t\t%s\n" % (score, name))
outfile.close()

if hasHighScore(wins):
setHighScores(wins, getName(wins))
 
C

Chris

I'm writing a game that uses two functions to check and see if a file
called highScoresList.txt exists in the main dir of the game program.
If it doesn, it creates one. That part is working fine. The problem is
arising when it goes to read in the high scores from the file when I
play again.

This is the error msg python is giving me

Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
main()
File "I:\PYTHON\PROJECT #3\PROJECT3.PYW", line 330, in main
if(hasHighScore(wins) == True):
File "I:\PYTHON\PROJECT #3\PROJECT3.PYW", line 175, in hasHighScore
scores,names = string.split(line,"\t")
ValueError: need more than 1 value to unpack

Here's the relavant code:

def hasHighScore(score):
#opens highScoresList.txt
infile = open("highScoresList.txt",'r')
scores = [0,0,0]
names = ["","",""]

#reads in scores from highScoresList.txt
i=0
for line in infile.readlines():
scores,names = string.split(line,"\t")
names=string.rstrip(names)
i += 1
infile.close()

#compares player's score with those in highScoresList.txt
i=0
for i in range(0,len(scores)):
if(score > int(scores)):
return True
else:
return False

def setHighScores(score,name):
#opens highScoresList.txt
infile = open("highScoresList.txt",'r')
scores = [0,0,0]
names = ["","",""]

#reads in scores from highScoresList.txt
i=0
for line in infile.readlines():
scores,names = string.split(line,"\t")
scores=int(scores)
names=string.rstrip(names)
i += 1
infile.close()

#shuffles thru the highScoresList.txt and inserts player's score if
higher then those in file
i=len(scores)
while(score > scores[i-1] and i>0):
i -= 1

scores.insert(i,score)
names.insert(i,name)
scores.pop(len(scores)-1)
names.pop(len(names)-1)

#writes new highScoresList.txt
outfile = open("highScoresList.txt","w")

outfile.write (" High Score Name \n")
outfile.write ("-------------------------------------------------\n")

i=0
for i in range(0,len(scores)):
outfile.write("\t" + str(scores) + "\t\t\t" + names + "\n")
outfile.close()

And here's the call to the functions at the end of my game, included in
the error msg.

#adds player's score to high score list if high enough
if(hasHighScore(wins) == True):
setHighScores(wins,getName(wins))

And this is what the text file looks like when it happens.

High Score Name
-------------------------------------------------
15 SHAWN
0
0

The answer is probably simple, I've just been working on this program so
long that my brain has turned to mush. Any help would be much
appreciated...thanks.


Your first two lines in your highscores file has no Tab Characters.
When reading the file you could do:

for (i, line) in file_input:
if i < 2:
continue

# do normal file parsing


There are better ways to structure your code though, but that's for
you.
 
C

Chris

I'm writing a game that uses two functions to check and see if a file
called highScoresList.txt exists in the main dir of the game program.
If it doesn, it creates one. That part is working fine. The problem is
arising when it goes to read in the high scores from the file when I
play again.
This is the error msg python is giving me
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
main()
File "I:\PYTHON\PROJECT #3\PROJECT3.PYW", line 330, in main
if(hasHighScore(wins) == True):
File "I:\PYTHON\PROJECT #3\PROJECT3.PYW", line 175, in hasHighScore
scores,names = string.split(line,"\t")
ValueError: need more than 1 value to unpack

Here's the relavant code:
def hasHighScore(score):
#opens highScoresList.txt
infile = open("highScoresList.txt",'r')
scores = [0,0,0]
names = ["","",""]
#reads in scores from highScoresList.txt
i=0
for line in infile.readlines():
scores,names = string.split(line,"\t")
names=string.rstrip(names)
i += 1
infile.close()

#compares player's score with those in highScoresList.txt
i=0
for i in range(0,len(scores)):
if(score > int(scores)):
return True
else:
return False

def setHighScores(score,name):
#opens highScoresList.txt
infile = open("highScoresList.txt",'r')
scores = [0,0,0]
names = ["","",""]
#reads in scores from highScoresList.txt
i=0
for line in infile.readlines():
scores,names = string.split(line,"\t")
scores=int(scores)
names=string.rstrip(names)
i += 1
infile.close()

#shuffles thru the highScoresList.txt and inserts player's score if
higher then those in file
i=len(scores)
while(score > scores[i-1] and i>0):
i -= 1
scores.insert(i,score)
names.insert(i,name)
scores.pop(len(scores)-1)
names.pop(len(names)-1)

#writes new highScoresList.txt
outfile = open("highScoresList.txt","w")
outfile.write (" High Score Name \n")
outfile.write ("-------------------------------------------------\n")
i=0
for i in range(0,len(scores)):
outfile.write("\t" + str(scores) + "\t\t\t" + names + "\n")
outfile.close()

And here's the call to the functions at the end of my game, included in
the error msg.
#adds player's score to high score list if high enough
if(hasHighScore(wins) == True):
setHighScores(wins,getName(wins))
And this is what the text file looks like when it happens.
High Score Name
The answer is probably simple, I've just been working on this program so
long that my brain has turned to mush. Any help would be much
appreciated...thanks.

Your first two lines in your highscores file has no Tab Characters.
When reading the file you could do:

for (i, line) in file_input:
if i < 2:
continue

# do normal file parsing

There are better ways to structure your code though, but that's for
you.


Apologies, I meant 'in enumerate(file_input)'
 
S

Samuel

I'm writing a game that uses two functions to check and see if a file
called highScoresList.txt exists in the main dir of the game program. If
it doesn, it creates one. That part is working fine. The problem is
arising when it goes to read in the high scores from the file when I
play again.

Not your original problem, but you should want to look at this instead of
creating yet another parser:

http://docs.python.org/lib/RawConfigParser-objects.html

-Samuel
 
D

Dennis Lee Bieber

File "I:\PYTHON\PROJECT #3\PROJECT3.PYW", line 175, in hasHighScore
scores,names = string.split(line,"\t")
ValueError: need more than 1 value to unpack

This implies that line doesn't have TWO items to be
assigned...

BTW: don't use the string module, its use has been deprecated for
some time -- the only things in it that are still really useful are some
of the character type constants.
Here's the relavant code:

def hasHighScore(score):
#opens highScoresList.txt
infile = open("highScoresList.txt",'r')
scores = [0,0,0]
names = ["","",""]
Note that scores and names are function local names, they do not
carry over outside the function.
#reads in scores from highScoresList.txt
i=0
for line in infile.readlines():

Unless you are using an old, old, Python, you don't need readlines()
here (readlines() reads the entire file into a list of lines first, then
feeds them to the for statement; just use infile and the newer
iterator protocol will fetch a line as needed by the for.
scores,names = string.split(line,"\t")
names=string.rstrip(names)
i += 1
infile.close()

#compares player's score with those in highScoresList.txt
i=0
for i in range(0,len(scores)):
if(score > int(scores)):
return True
else:
return False

said:
#writes new highScoresList.txt
outfile = open("highScoresList.txt","w")

outfile.write (" High Score Name \n")
outfile.write ("-------------------------------------------------\n")

Note that if this is the file you are trying to read at the start,
you've got two lines of text that are NOT scores, and the second has
only one field in it...

The answer is probably simple, I've just been working on this program so
long that my brain has turned to mush. Any help would be much
appreciated...thanks.

The idea, I take it, is to maintain a list of the top three highest
scorers?

-=-=-=-=-=-=-=-=-
import os

TOPTHREEFILE = "highScoresList.txt"

# initialize empty TopThree list
scoreList = [ ( 0, "" ),
( 0, "" ),
( 0, "" ) ]

def loadPriorScores():
if os.path.exists(TOPTHREEFILE):
fin = open(TOPTHREEFILE, "r")
for i, ln in enumerate(fin):
flds = ln.split("\t")
if len(flds) == 2:
#scoreList is mutable object, so no global needed
#we are just mutating it here
scoreList = (int(flds[0]), flds[1])
else:
print "**** Bad line found in %s" % TOPTHREEFILE
fin.close()

def updateScores(score, player):
global scoreList #precaution as we are doing nasty things
# add current candidate score to the end of the list
# making it a four entry list
scoreList.append( (score, player) )
# sort the list; should work on the score first,
# then name if same scores
scoreList.sort()
# reverse the sort so high score is on top
scoreList.reverse()
# keep only the top three entries
scoreList = scoreList[:3]
return scoreList[0] == (score, player)

def saveCurrentScores():
fout = open(TOPTHREEFILE, "w")
for (s, p) in scoreList:
fout.write("%s\t%s\n" % (s, p))
fout.close()

def displayScores():
print " High Score Player "
print " ---------------- ------------------"
for (s, p) in scoreList:
print " %16s %16s" % (s, p)


if __name__ == "__main__":
#just some dummy data to test with
test = [ ( 34, "Trethamkar"),
( 16, "Rathulf"),
( 21, "Cwiculf"),
(2383, "We Have a Winnuh!"),
(2383, "We Have a Tie!") ]
for (s, p) in test:
print "Loading old scores"
loadPriorScores()
print "Displaying older scores\n"
displayScores()
print "Updating with player %s" % p
if updateScores(s, p):
print "\nPlayer %s has the new high score\n" % p
else:
print "\nPlayer %s does NOT have the high score\n" % p
displayScores()
print "Saving score list"
-=-=-=-=-=-=-=-
Loading old scores
Displaying older scores

High Score Player
---------------- ------------------
0
0
0
Updating with player Trethamkar

Player Trethamkar has the new high score

High Score Player
---------------- ------------------
34 Trethamkar
0
0
Saving score list
Loading old scores
Displaying older scores

High Score Player
---------------- ------------------
34 Trethamkar
0
0
Updating with player Rathulf

Player Rathulf does NOT have the high score

High Score Player
---------------- ------------------
34 Trethamkar
16 Rathulf
0
Saving score list
Loading old scores
Displaying older scores

High Score Player
---------------- ------------------
34 Trethamkar
16 Rathulf
0
Updating with player Cwiculf

Player Cwiculf does NOT have the high score

High Score Player
---------------- ------------------
34 Trethamkar
21 Cwiculf
16 Rathulf
Saving score list
Loading old scores
Displaying older scores

High Score Player
---------------- ------------------
34 Trethamkar
21 Cwiculf
16 Rathulf
Updating with player We Have a Winnuh!

Player We Have a Winnuh! has the new high score

High Score Player
---------------- ------------------
2383 We Have a Winnuh!
34 Trethamkar
21 Cwiculf
Saving score list
Loading old scores
Displaying older scores

High Score Player
---------------- ------------------
2383 We Have a Winnuh!
34 Trethamkar
21 Cwiculf
Updating with player We Have a Tie!

Player We Have a Tie! does NOT have the high score

High Score Player
---------------- ------------------
2383 We Have a Winnuh!
2383 We Have a Tie!
34 Trethamkar
Saving score list
-=-=-=-=-=-=-=-


Due to the use of .reverse(), even though an ascending sort would
have "We Have a Tie" before "We Have a Winnuh!", the reverse changes
that. Supplying a sort function to .sort() that handles descending score
and ascending name would allow for removing the .reverse()
--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 
B

Bruno Desthuilliers

Shawn Minisall a écrit :
I'm writing a game that uses two functions to check and see if a file
called highScoresList.txt exists in the main dir of the game program.
If it doesn, it creates one. That part is working fine. The problem is
arising when it goes to read in the high scores from the file when I
play again.

This is the error msg python is giving me

Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
main()
File "I:\PYTHON\PROJECT #3\PROJECT3.PYW", line 330, in main
if(hasHighScore(wins) == True):
File "I:\PYTHON\PROJECT #3\PROJECT3.PYW", line 175, in hasHighScore
scores,names = string.split(line,"\t")
ValueError: need more than 1 value to unpack

Here's the relavant code:

def hasHighScore(score):
#opens highScoresList.txt
infile = open("highScoresList.txt",'r')


hardcoded file names are a bad idea. And FWIW, your file will be looked
for in the current wirking directory - which is not necessarily the
"main dir of the game program".
scores = [0,0,0]
names = ["","",""]

#reads in scores from highScoresList.txt
i=0
for line in infile.readlines():

You can iterate directly over the file.
scores,names = string.split(line,"\t")


string.split(str, sep) is long time deprecated. Use str methods instead:
s, n = line.split('\t')

Also, this will obviously raise if the line doesn't have exactly one tab
in it. Like, ie, it's an empty line....
names=string.rstrip(names)
i += 1


You can use enumerate(iterable) instead of manually counting lines.
Also, what if your file has more than 3 lines ?

infile.close()
#compares player's score with those in highScoresList.txt
i=0
for i in range(0,len(scores)):

You obviously don't know how to use Python's for loop:

for item in scores:
# now use item instead of scores
if(score > int(scores)):
return True
else:
return False


You have a logic error here. This will only compare the first item in
your score list. You want something like:

for item in score:
if score > int(item):
return True
return False
def setHighScores(score,name):
#opens highScoresList.txt
infile = open("highScoresList.txt",'r')
scores = [0,0,0]
names = ["","",""]

#reads in scores from highScoresList.txt
i=0
for line in infile.readlines():
scores,names = string.split(line,"\t")
scores=int(scores)
names=string.rstrip(names)
i += 1
infile.close()


hem... don't you see something like a duplication here ? By all mean
extract out this code in a 'read_scores' function.
#shuffles thru the highScoresList.txt and inserts player's score if
higher then those in file
i=len(scores)
while(score > scores[i-1] and i>0):
i -= 1

scores.insert(i,score)
names.insert(i,name)
scores.pop(len(scores)-1)
names.pop(len(names)-1)

OMG.

This is ten times more complicated than it needs to be.
#writes new highScoresList.txt
outfile = open("highScoresList.txt","w")

outfile.write (" High Score Name \n")
outfile.write ("-------------------------------------------------\n")

i=0
for i in range(0,len(scores)):
outfile.write("\t" + str(scores) + "\t\t\t" + names + "\n")


If your file is formated that way, no surprise your code breaks. None of
what you write in it matches the expectations of the code that reads it.
outfile.close()
And here's the call to the functions at the end of my game, included in
the error msg.

#adds player's score to high score list if high enough
if(hasHighScore(wins) == True):
setHighScores(wins,getName(wins))

And you're doing two times the same parsing of the file....
The answer is probably simple,

The answer to your question is indeed quite simple : either rewrite the
code that reads the file to make it matches what you wrote in the file,
or rewrite the code that writes the file to make it match the
expectations of the code that reads it. IOW : make both parts of the
code work on a same file format !-)

Also, learning to make effective use of Python's features would help !-)

Here's a possible reimplementation of your code - not tested, so it may
have bugs, but it should do the trick.

The file format is a very simple 'score:name' per line. Nothing else.
(heck, this file is for storing data, it's not meant to be seen by the
user).

The hiscore file full path must be passed when instantiating the
Hiscores object (that is, when initializing your program - you just need
one Hiscore object for the whole lifetime of your program). You must
also pass the max number of hiscores you want to keep, and an optional
flag telling if an error while reading the hiscore file should raise an
exception or be ignored (ending up using an empty hiscore list).

hiscores = HiScores('/path/to/your/file.ext', 3)

Once done, you just use it:

if hiscores.update(42, 'bibi'):
print "Yay, your a boss"
else:
print "try again..."


# hiscores.py
import sys

def _read_scores(path):
f = open(path)
# we don't expect a huge file so it's simpler to
# read it all in memory
lines = f.readlines()
f.close()

scores = []
for line in filter(None, map(str.strip, lines)):
try:
score, name = line.split(':')
score = int(score)
except ValueError, e:
# either the lines was not score:name or
# score wasn't a proper value for an int
err = "File %s : incorrect file format" \
% path
raise ValueError(err)
else:
scores.append((score, name))

# supposed to be already sorted, but we want to be sure.
# NB : natural sort will do the RightThing(tm) here
scores.sort()
return scores

def _write_scores(path, scores):
scores = "\n".join(["%s:%s" % item for item in scores])
f = open(path, 'w')
f.write(scores)
f.close()

class HiScores(object):
def __init__(self, path, nb_scores, raise_on_error=False):
self._path = path
self._nb_scores = nb_scores
try:
self._scores = _read_scores(path)[0:self.nb_scores - 1]
except (IOError, ValueError), e:
if raise_on_error:
raise
else:
# log the error
err = "Error while reading hiscore file %s : %s" \
% (path, e)
print >> sys.stderr, err
# use an empty list instead
self._scores = []

def index(self, score):
for i, s in enumerate(self._scores):
if score > s[0]:
return i
return -1

def update(self, score, name):
index = self.index(score)
if index == -1:
return False

self._scores.insert(index, (score, name))
self._scores.pop()
_write_scores(self._path, self._scores)
return True

def is_hi_score(self, score):
return self.index(score) > -1

HTH
 
B

Bruno Desthuilliers

Bruno Desthuilliers a écrit :
(snip)
# hiscores.py
import sys

def _read_scores(path):
f = open(path)
# we don't expect a huge file so it's simpler to
# read it all in memory
lines = f.readlines()
f.close()

scores = []
for line in filter(None, map(str.strip, lines)):
try:
score, name = line.split(':')
score = int(score)
except ValueError, e:
# either the lines was not score:name or
# score wasn't a proper value for an int
err = "File %s : incorrect file format" \
% path
raise ValueError(err)
else:
scores.append((score, name))

# supposed to be already sorted, but we want to be sure.
# NB : natural sort will do the RightThing(tm) here
scores.sort()

oops ! missing line here:

score.reverse()
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Highscores list 0
C# problem 1
Top 10 players minheap sort - need help 1
Python problem 1
Having troubles with list methods 2
Pointers in python? 1
HELP PLEASE 4
Chatbot 0

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,816
Latest member
SapanaCarpetStudio

Latest Threads

Top