Incrementing a score system in Python

Viewed 161

:D I've make a little rock paper scissors game in Python just for fun and practice and I've been trying to implement a little scoring system that doesn't seem to want to work properly and I'm not sure how to solve the problem.

import random
import messages

def gameOn():
  choice = ["rock", "paper", "scissors"]

  computer_choice = random.choice(choice)
  player_choice = input("Please chose Rock/Paper/Scissors: ")
  player_choice = player_choice.lower()
  total_score = 0

  while True:

    #Makes sure the user enters a valid option.
    if player_choice not in("rock", "paper", "scissors"):
      print("Choice is not correct!")

    #Prints in case both the computer and the player chose the same option.
    elif computer_choice == player_choice:
      print("You chose the same.")
    
    #Computer choses ROCK.
    elif computer_choice == "rock" and player_choice == "paper":
      print(messages.win[0])
      total_score += 1
      print(total_score)
    elif computer_choice == "rock" and player_choice == "scissors":
      print(messages.lose[0])

    #Computer choses PAPER.
    elif computer_choice == "paper" and player_choice == "rock":
      print(messages.lose[1])
    elif computer_choice == "paper" and player_choice == "scissors":
      print(messages.win[1])
      total_score += 1
      print(total_score)

    #Computer choses SCISSORS.
    elif computer_choice == "scissors" and player_choice == "rock":
      print(messages.win[2])
      total_score += 1
      print(total_score)
    elif computer_choice == "scissors" and player_choice == "paper":
      print(messages.lose[2])
      
    #Asks the user if he/she wants to play again and restarts the loop if so.
    answer = input("Would you like to play again or see your score? Yes/No/Score ")
    if answer in ("yes", "Yes", "y", "Y", "yup"):
      print("Game starting again!")
      gameOn()
    elif answer in ("Score", "score"):
      print("Your total score is " + str(total_score)) 
      answer = input("Would you like to play again or see your score? Yes/No/Score ")
      print("Game starting again!")
      gameOn()
    else:
      print("Goodbye!")
    break

gameOn()

The incrementation in itself works but what I want to do is, if the player wins multiple round and at the end writes "score" he should be able to see all the points he has earned. At the moment the score variable get reset every time a new game starts so the score of the use is always either 0 or 1 if he won the round. How could I prevent this behavior? Thank you very much :D and I hope it's not a too stupid question.

3 Answers

I would suggest defining a parameter to your gameOn function, so it looks like this:

def gameOn(total_score=0):
  # REMOVE this following line:
  total_score = 0
  # because we already defined it on parameter

  # when user wins, and you call the function again,
  # give current total_score to it
  gameOn(total_score)

since in each function call you are giving the current score, now your app should be able to keep track of actual total score

There are 2 different ways to answer this, depending on the meaning of «every time a new game starts».

Do you want to persist the score if you call the gameOn function multiple times?
Or do you want to persist the score also if you run the program again?

Persisting the score between gameOn calls

The problem is the scope of your total_score variable, which is local. Hence it’s cleaned after each gameOn execution. The simplest way to work around this is to set it as global:

import random
import messages

# Total score is initialized outside of any game
total_score = 0

def gameOn():
  choice = ["rock", "paper", "scissors"]

  computer_choice = random.choice(choice)
  player_choice = input("Please chose Rock/Paper/Scissors: ")
  player_choice = player_choice.lower()
  global total_score
  # Then the rest of your existing function
  # ...

Advice: With time, you’ll get better in Python, and you’ll realize such global variable is usually considered bad, because of the lack of isolation it has. For larger projects, relying on globally defined stuff makes the code more difficult to evolve, increases the cognitive load of the developer, makes it harder to test... but for such a small script it’s just perfectly fine. My point is: it’s handy, but please keep in mind there are other ways to do it. They are more complex, and over-engineered in this case, but the key take away shouldn’t be thought as "I need to use global variable as soon as I want to persist a state" ;)

Persisting the score between runs.

If your goal is to keep the score between every time you run the script, then you need to save it "outside" of the current Python session memory.
A very simple way to do this is to save it to a file. Python’s built-in pickle library is made for that (there are many other options, depending on if you want this to be usable by other programs or not, or by humans. When it’s just for Python, pickle is super simple and fast and reliable)

In this case, what you would need is to:

  • load the existing score when the game starts, if an existing score exists
  • save it at the end of the game
import random
import messages
import pickle
import os


def gameOn():
  choice = ["rock", "paper", "scissors"]

  computer_choice = random.choice(choice)
  player_choice = input("Please chose Rock/Paper/Scissors: ")
  player_choice = player_choice.lower()
 
  score_file = "score.dat"
  # Check if an existing score existed
  if os.path.isfile(score_file):
      with open(score_file, "rb") as f:
        total_score = pickle.load(f)
  else:
      total_score = 0

  # Then the rest of your existing function
  # ...
  # and at the end of the function, we save the score to the file
  with open(score_file, "wb") as f:
      pickle.dump(total_score, f)

This should give you pointers to what you exactly want to achieve.

I would not advise using recursion for this. You also shouldn't need to use global variables.

I would rather just loop with while True in your gameOn function and break if the player wants to exit, so that your score is kept in scope.

Also your "Choice is not correct!" was not working because of the indentation.

import random
import messages

def gameOn():
        choice = ["rock", "paper", "scissors"]
        total_score = 0

    while True:    
        computer_choice = random.choice(choice)
        player_choice = input("Please chose Rock/Paper/Scissors: ")
        player_choice = player_choice.lower()

        while True:
            #Makes sure the user enters a valid option.
            if player_choice in("rock", "paper", "scissors"):
                break
            print("Choice is not correct!")

        #Prints in case both the computer and the player chose the same option.
        elif computer_choice == player_choice:
            print("You chose the same.")
    
        #Computer choses ROCK.
        elif<computer_choice == "rock" and player_choice == "paper":
            print(messages.win[0])
            total_score += 1
            print(total_score)
        elif computer_choice == "rock" and player_choice == "scissors":
            print(messages.lose[0])

        #Computer choses PAPER.
        elif computer_choice == "paper" and player_choice == "rock":
            print(messages.lose[1])
        elif computer_choice == "paper" and player_choice == "scissors":
            print(messages.win[1])
            total_score += 1
            print(total_score)

        #Computer choses SCISSORS.
        elif computer_choice == "scissors" and player_choice == "rock":
            print(messages.win[2])
            total_score += 1
            print(total_score)
        elif computer_choice == "scissors" and player_choice == "paper":
        print(messages.lose[2])
  
        #Asks the user if he/she wants to play again and restarts the loop if so.
        answer = input("Would you like to play again or see your score? Yes/No/Score ")

        if answer in ("Score", "score"):
            print("Your total score is " + str(total_score)) 
            answer = input("Would you like to play again or see your score? Yes/No/Score ")
            print("Game starting again!")
        elif answer in ("yes", "Yes", "y", "Y", "yup"):
            print("Game starting again!")
        else:
            print("Goodbye!")
            break #this makes your game stop

gameOn()
Related