Solo
Solo

Reputation: 43

Python Sorting a leaderboard from Highest to Lowest scores and Top 5 (external file)

Excuse the very poorly worded title!

For my computer science GCSE, I have been given a 20 hour project. The most of it is completed and fully functional, however I am struggling with the last step.

I've made it so a user can store their final score into an external file, and that file's content is printed at the end of the game. However, I would like it to print only the top 5 scorers and for the scores to be assorted from highest to lowest.

A number next to each position to show their place on the board would be cool, but if that's difficult to do, I'm fine with skipping over it.

Here's the section of code for defining the leaderboard:

    def leaderboard():
  print ("\n")
  print ("⬇ Check out the leaderboard ⬇") #LEADERBOARD SECTION
  f = open('H_Highscore.txt', 'r')
  leaderboard = [line.replace('\n','') for line in f.readlines()]
  for i in leaderboard:
      print(i)
  f.close()
  time.sleep(10)
  sys.exit()

And here is the code for writing to the leaderboard:

user = str(input("Enter a name to save your highscore: "))
                    file = open ("H_Highscore.txt", "a")
                    file.write("\n")
                    file.write(user)
                    file.write(",")
                    file.write(str(score)) # (int(x)) can not be written
                    file.write("pts")
                    file.write("\n")
                    file.close()
                    time.sleep(0.5)
                    leaderboard()
                    sys.exit()

If needed, here's the entirety of the program:

#Casey_Neale
import sys
import random
import time
import math
import csv
import time, sys
import datetime
newaccounts=True   #DEVELOPMENT
loggedIn=False     #PURPOSES
yn=True            #ONLY
from threading import Timer

TIMELIMIT = 5.0 #Timer in secs, lowered for development and testing
time_ran_out = False #Global 

'''
Known bugs and needed improvements are stored in G_Bugs.txt
The report for this project is entitled "D_ProjectReportTemplate.docx
Songs stored externally to F_Songs.txt
'''

def tutorial(): #Games introduction
  slow_print("Your aim is to get as many points as possible...\n")
  #print("\n")
  time.sleep(1.5)
  slow_print("You need to guess the name of each song to gain points...\n")
#  print("\n")
  time.sleep(1.5)
  slow_print("You have two guesses for each song...\n")
 # print("\n")
  time.sleep(1.5)
  slow_print ("The artist name is provided for you...\n")
  time.sleep(1.5)
  slow_print("There is an ingame timer, so good luck!")
  time.sleep(1.5)
  print("\n")
  print("\n")

def slow_print(s):
  for c in s:
    sys.stdout.write( '%s' % c )
    sys.stdout.flush()
    time.sleep(0.03)

def timeout():
    global time_ran_out

    time_ran_out = True

def leaderboard():
  print ("\n")
  print ("⬇ Check out the leaderboard ⬇") #LEADERBOARD SECTION
  f = open('H_Highscore.txt', 'r')
  leaderboard = [line.replace('\n','') for line in f.readlines()]
  for i in leaderboard:
      print(i)
  f.close()
  time.sleep(10)
  sys.exit()

def loginsys():
  doublecheck=True
  while doublecheck == True:
    slow_print("➡Welcome | Are you a registered user?\n[Y/N]: ")
    verifyRegister = input()
    print (" ")
    if verifyRegister == "n" or verifyRegister == "N":  #If the user is not already registered
      if newaccounts == True:
        loop=True
        while loop == True:
            username = input ("Please enter a username\n[User]: ")#Prompts the user to provide a desired username
            print (" ")#Prompts for username
            checkusername = input ("Please retype your username\n[Verify]: ")#Verifys username
            print (" ")#Prompts to verify username
            if checkusername != username:
              print ("Invalid, please try again")
              loop=True
            else:
              loop=False       
              time.sleep(0.5)
              passloop=True
              while passloop == True:
                      password = input ("Please enter a password\n[Password]: ") #Prompts the user to provide a desired password
                      print (" ")#Prompts for password
                      checkpassword = input ("Please retype your password\n[Verify]: ") #Verifys password
                      print (" ")#Prompts to verify password
                      if checkpassword != password:
                        print ("Invalid, please try again")
                        print (" ")
                        passloop=True
                      else:
                        passloop=False
                        file = open("C_AccountData.txt","a") #Opens the file C_AccountData.txt in write mode/opens connection
                        file.write("USRN:") #Prefix Username to make the file easier to read
                        file.write(username) #Writes the username 
                        file.write("|") #Partition for visual ease to make the file easier to read
                        file.write("PSWD:") #Prefix Password to make the file easier to read
                        file.write(password)#Writes the password
                        file.write("\n") #New line to make the file easier to read
                        file.close() #Closes file/ends connection
                        print ("✓Your account has been created") #Verifies that the account has been made to the user
                        time.sleep(2)
                        print ("\n")
                        doublecheck=True #Loop

    if verifyRegister == "Y" or verifyRegister == "y":
      loop=True
      if loop == True:
          user = input("[User]: ")
          passw = input("[Password]: ")
          if passw == (""):
            print("You did not enter a password")
            loop=True
            time.sleep(2)
            sys.exit() #If the end user does not enter a password, the program will terminate. This is to prevent a security concern where users can freely login to existing accounts by leaving the password field empty
            break
          f = open("C_AccountData.txt", "r")
          for line in f.readlines():
            uspwd = line.split("|")
            us = uspwd[0]
            pw = uspwd[1]
            if (user in us) and (passw in pw):
              loop=False
              print("Login successful, welcome",user)
              print("\n")
              doublecheck=False
          else:
            if loop == True:
                  print ("\n")
                  print ("Sorry, your account details were not recognised. ") #Reject

    else:
      if verifyRegister != "Y" or verifyRegister != "y" or verifyRegister != "N" or verifyRegister != "n" or verifyRegister !="backup":
        print("\n")
        doublecheck=True

def pickSong_random():
    global time_ran_out

    score = 0
    lives = 5
    songFile = open("F_Songs.txt", "r")
    songList = songFile.readlines() # Reads from the bridged file
    songFile.close()

    while True:
        chosenSong = random.choice(songList)
        chosenSong = chosenSong.strip("\n")
        artistAndSong = chosenSong.split(":") # Defines song split

        toDisplay = ""
        toDisplay += artistAndSong[0] + ": "
        songTitleWords = artistAndSong[1].split(" ")

        for word in songTitleWords:
            # loop through
            toDisplay += word[0] + " "
        print(toDisplay)
        # print("2" +toDisplay)
        toDisplay = toDisplay.strip("None")

        guesses = 0
        timer = Timer(TIMELIMIT, timeout)  # Create a timer thread object.
        time_ran_out = False  # Initialize the variable the callback modifies.

        timer.start()  # Start the background timer.
        while guesses < 2:
            if time_ran_out:
                print('Times up!')
                time.sleep(3)
                print ("You managed to score",score,"point(s)")
                time.sleep(3)
                print("\n")
                slow_print("Would you like to play again?")
                playAgain = input("\n[Y/N]: ")
                if playAgain == ("n") or playAgain == ("N"):
                    print("\n")
                    # user variable is not saved from the login system as it is
                    # defined as a function separately
                    user = str(input("Enter a name to save your highscore: "))
                    file = open ("H_Highscore.txt", "a")
                    file.write("\n")
                    file.write(user)
                    file.write(",")
                    file.write(str(score)) # (int(x)) can not be written
                    file.write("pts")
                    file.write("\n")
                    file.close()
                    time.sleep(0.5)
                    leaderboard()
                    sys.exit()
                if playAgain == ("Y") or playAgain == ("y"):
                    print("Your last score was", score,", lets see if you can beat it this time...")
                    time.sleep(1)
                    print("\n")
                    pickSong_random()
                time.sleep(2)
                break

            guesses += 1
            guess = input("[Enter your guess]: ")

            # Guess checking
            if guess.lower() == artistAndSong[1].lower():
                print("✓Correct! The song was '" + artistAndSong[1]
                        + "' by " + artistAndSong[0])
                print("It took you", guesses, "guess(es)!")
                if guesses == 1:
                    print("\n")
                    print("↑(+3 points)↑")
                    print("\n")
                    score += 3
                    break
                elif guesses == 2:
                    print("\n")
                    print("↑(+1 point)↑")
                    print("\n")
                    score += 1
                    break
            else:
                print("╳The song name isn't", guess, "\n")
                lives = lives-1
                if guesses == 2:
                    print("Sorry, you couldn't guess the song.")
                    print("\n")
            if lives == 0:
                print("You have no more lives to continue! Your score was:", score)
                time.sleep(3)
                print("\n")
                slow_print("Would you like to play again?")
                playAgain = input("\n[Y/N]: ")
                if playAgain == ("n") or playAgain == ("N"):
                    print("\n")
                    # user variable is not saved from the login system as it is
                    # defined as a function separately
                    user = str(input("Enter a name to save your highscore: "))
                    file = open ("H_Highscore.txt", "a")
                    file.write(user)
                    file.write(",")
                    file.write(str(score)) # (int(x)) can not be written
                    file.write("pts")
                    file.write("\n")
                    file.close()
                    time.sleep(0.5)
                    leaderboard()
                    sys.exit()
                if playAgain == ("Y") or playAgain == ("y"):
                    print("Your last score was", score,", lets see if you can beat it this time...")
                    time.sleep(1)
                    print("\n")
                    pickSong_random()

#if __name__ == '__main__':


print(" ___|)________________________________________________________")
print("|___/____________________________|___________________________||")
print("|__/|_______/|____/|_____/|______|___________________________||")
print("|_/(|,\____/_|___/_|____/_|______|___________________________||")
print("|_\_|_/___|__|__|__|___|__|___|__|___________________________||")
print("|   |     | ()  | ()   | ()   |  |                           ||")
print("| (_|   -()-  -()-   -()-   -()- | -()-  -()-  -()-   -()-   ||")
print("|________________________________|__|__()_|__()_|__()__|_____||")
print("|__/___\_._______________________|__|__|__|__|__|__|___|_____||")
print("|__\___|_._______________________|___\_|___\_|___\_|___|_____||")
print("|_____/__________________________|____\|____\|____\|_________||")
print("|____/___________________________|___________________________||")
print("             This project was developed by Casey Neale")
clockTime = time.asctime( time.localtime(time.time()) )
print ("                   ",clockTime) #Displays the current time and date. No real reason, just to look pleasing
print("\n")
print("\n")

loginsys() #LOGIN PROTOCOL
time.sleep(3)
#print("\n")
tutorial() #TUTORIAL PROTOCOL
slow_print ("\nPrepare yourself! The game will begin in...\n") #COUNTDOWN TO GAME TIME
time.sleep(0.5)
print("\n")
slow_print("5...")
time.sleep(0.5)
print("\n")
slow_print("4...")
time.sleep(0.5)
print("\n")
slow_print ("3...")
time.sleep(0.5)
print("\n")
slow_print ("2...")
time.sleep(0.5)
print("\n")
slow_print ("1...")
time.sleep(0.5)
print("\n")
print("\n")
print("\n")
print(" ________  _________  ________  ________  _________ ") 
print("|\   ____\|\___   ___\\   __  \|\   __  \|\___   ___\ ")
print("\ \  \___|\|___ \  \_\ \  \|\  \ \  \|\  \|___ \  \_|")
print(" \ \_____  \   \ \  \ \ \   __  \ \   _  _\   \ \  \ ")
print("  \|____|\  \   \ \  \ \ \  \ \  \ \  \\  \|   \ \  \ ")
print("    ____\_\  \   \ \__\ \ \__\ \__\ \__\\ _\    \ \__\ ")
print("   |\_________\   \|__|  \|__|\|__|\|__|\|__|    \|__|")
print("    \|_________|                                       ")

print("\n")
print("\n")
pickSong_random() #GAME PROTOCOL
sec
sys.exit() #EXIT PROTOCOL

Obviously, this is a chore, so if you can't be bothered to try it, that's perfectly fine! Thanks for stopping by and have a fantastic day!

Upvotes: 1

Views: 7157

Answers (2)

Steve
Steve

Reputation: 496

Pointers, break the problem into a series of steps and read up on:

Think about maybe:

  • reading your high score file, in the same format as you write it,line by line
  • get the relevant text and numbers from the relevant lines
  • append each (username, score) as a tupple to a list
  • sort the list in reverse
  • print the first 5 items on the list

Code Fragments:

scores.append((user_name,score)) #core is of type list

i = 0
while i < limit:
    item = sorted_list[i]
    print ("first item of tupple: {} second item:{}".format(item[0],item[1]))
    i+=1

Hint: Don't forget to cast the score from string to int before sorting.

Upvotes: 0

Anton
Anton

Reputation: 67

I recommend turning the leaderboard list of strings into a list of (str, int) tuples, sort the list and print the top 5 like this:

leaderboard_tuples = [tuple(x.split(',')) for x in leaderboard]
leaderboard_tuples.sort(key=lambda tup: tup[1])

Upvotes: 1

Related Questions