perfect.
perfect.

Reputation: 1

How do I write the scores of my game into the leaderboard.txt and display the top 5 scores only with each player's name

I'm currently doing a dice game for my school programming project, and it includes the rules: 'Stores the winner’s score, and their name, in an external file' and 'Displays the score and player name of the top 5 winning scores from the external file.' I've done everything in my game apart from the leaderboard. I am able to write the name and score of the user into the txt file, but I am unsure of how to then sort it, and would also like when people first start the program can use the menu to go to the leaderboard where it would then read the txt file and print the top 5 scores in order including the names. I've checked loads of over questions similar to mine, but none of them exactly worked for my code as I kept on getting errors implementing other people's code into mine which just weren't compatible with my layout.

(deleted)

Thanks in advance, I've never used stack overflow to ask a question so I apologize if there's anything I've done wrong in my post.

Upvotes: 0

Views: 875

Answers (1)

exhuma
exhuma

Reputation: 21727

You did good on the question. You stated the problem clearly and, most importantly, you added enough code to run the code so we can have a look at how the program behaves and what's going wrong. In this case nothing is going wrong which is good :)

Considering you mention that this is a school project I will not give you a fully copy/paste solution but will explain hopefully enough details on how to solve this on your own.

Now according to the question, you don't know how to sort your leaderboard. I ran the program a few times myself (after removing the sleeps because I am impatient 😋) and see that your leaderboard file looks like this:

90 - somename
38 - anothername
48 - yetanothername

To display this you must do two things:

  • Open the file and read the data
  • Convert the data from the file into something usable by the program

The first step seems to be something you already know as you already use open() to write into the file. Reading is very similar.

The next step is not so obvious if you are new to programming. The file is read as text-data, and you need to sort it by numbers. For a computer the text "10" is not the same a the number 10 (note the quotes). You can try this by opening a Python shell:

>>> 10 == 10
True
>>> 10 == "10"
False
>>> "10" == 10
False

And text sorts differently to numbers. So you one piece of the solution is to convert the text into numbers.

You will also get the data as lines (either using readlines() or splitlines() depending on how you use it. These line need to be split into score and name. The pattern in the file is this:

<score> - <name>

It is important to notice that you have the text " - " as separator between the two (including spaces). Have a look at the Python functions str.split() and str.partition(). These functions can be applied to any text value:

>>> "hello.world".split(".")
['hello', 'world']
>>> "hello.world".partition(".")
('hello', '.', 'world')

You can use this to "cut" the line into multiple pieces.

After doing that you have to remember the previous point about converting text to numbers.

As a last step you will need to sort the values.

When reading from the file, you can load the converted data into a Python list, which can then be sorted.

A convenient solution is to create a list where each element of that list is a tuple with the fields (score, name). Like that you can directly sort the list without any arcane tricks.

And finally, after sorting it, you can print it to the screen.

In summary

  • Open the file
  • Read the data from the file as "lines"
  • Create a new, empty list.
  • Loop over each line and...
    • ... split the line into multiple parts to get at the score and name separately
    • ... convert the score into a number
    • ... append the two values to the new list from point 3
  • Sort the list from point 3
  • Print out the list.

Some general thoughts

You can improve and simplify the code by using more functions

You already show that you know how to use functions. But look at the comments #THIS IS ROUND1 to #THIS IS ROUND5. The lines of code for each round are the same. By moving those lines into a function you will save a lot of code. And that has two benefits: You will only need to make a code-change (improvement or fix) in one place. And secondly, you guarantee that all blocks behave the same.

To do this, you need to think about what variables that block needs (those will be the new function arguments) and what the result will be (that will be the function return value).

A simple example with duplication:

print("round 1")
outcomes = []
value1 = random(1, 100)
value2 = random(1, 100)
if value1 > value2:
    outcomes.append("A")
else:
    outcomes.append("B")

print("round 2")
outcome = ""
value1 = random(1, 100)
value2 = random(1, 100)
if value1 > value2:
    outcomes.append("A")
else:
    outcomes.append("B")

Rewritten with functions

def run_round(round_name):
    print(round_name)
    value1 = random(1, 100)
    value2 = random(1, 100)
    if value1 > value2:
        return "A"
    else:
        return "B"

outcomes = []
result_1 = run_round("round 1")
outcomes.append(result_1)
result_2 = run_round("round 2")
outcomes.append(result_2)

As you can see, the second code is much shorter and has no more duplication. Your code will have more function arguments. It is generally a challenge in programming to organise your code in such a way that functions have few arguments and no complex return values. Although, as long as it works nobody will look too closely ;)

Safe way to ask for a password

You can use getpass() from the module getpass() to prompt for a password in a secure manner:

from getpass import getpass
password = getpass()

Note however, if you are using PyCharm, this causes some issues which are out of scope of this post. In that case, stick with input().

Sleeps

The "sleep()" calls are nice and give you the chance to follow the program, but make it slow to test the program. Consider to use smaller values (comma-values are possible), or, even better, write your own function that you can "short-circuit" for testing. Something like this:

import time


ENABLE_SLEEP = True

def sleep(s):
    if ENABLE_SLEEP:
        time.sleep(s)

print("some code")
sleep(1)
print("more code")
sleep(4)

You will then use your own sleep() function anytime you want to wait. That way, you can simply set the variable ENABLE_SLEEP to False and your code will run fast (for testing).

Upvotes: 2

Related Questions