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[i],names[i] = 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[i],names[i] = 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[i]=string.rstrip(names[i]) > 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[i] > if(score > int(scores[i])): > 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[i],names[i] = string.split(line,"\t") > scores[i]=int(scores[i]) > names[i]=string.rstrip(names[i]) > 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[i]) + "\t\t\t" + names[i] + "\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 -- http://mail.python.org/mailman/listinfo/python-list