"Rock, Paper, Scissors" game - follow-up This is a follow-up to "&quot;Rock, Paper, Scissors&quot; game". I did almost everything the answers recommended and I hope you like it.

import os
from random import choice


def player_choice():
    while True:
        print("Rock, paper or scissors?")
        choice = input("&gt;").capitalize()
        if choice in ('Rock', 'Paper', 'Scissors'):
            return choice


def win_msg(player_choice, computer_choice):
    msg = f"{player_choice} beats {computer_choice}. You won!"
    return msg


def lose_msg(player_choice, computer_choice):
    msg = f"{computer_choice} beats {player_choice}. You lost!"
    return msg


def computer_choice():
    return choice(('Rock', 'Paper', 'Scissors'))


def show_statistics(scores):
    os.system('cls' if os.name == 'nt' else 'clear')
    print(f"Wins: {scores[0]}\nLosses: {scores[1]}\nDraws: {scores[2]}")


def game_outcome(player, computer):
    if player == computer:
        return 'Draw'
    elif player == 'Rock':
        if computer == 'Paper':
            return 'Lose'
        else:
            return 'Win'
    elif player == 'Paper':
        if computer == 'Rock':
            return 'Win'
        else:
            return 'Lose'
    else:
        if computer == 'Rock':
            return 'Lose'
        else:
            return 'Win'


def show_results(outcome, player, computer):
    if outcome == 'Win':
        print(win_msg(player, computer))
    elif outcome == 'Lose':
        print(lose_msg(player, computer))
    else:
        print("Draw. Nobody wins or losses.")


def update_scores(scores, outcome):
    new_scores = list(scores)
    if outcome == 'Win':
        new_scores[0] += 1
    elif outcome == 'Lose':
        new_scores[1] += 1
    else:
        new_scores[2] += 1
    new_scores = tuple(new_scores)
    return new_scores


def rock_paper_scissors(scores):
    player = player_choice()
    computer = computer_choice()
    outcome = game_outcome(player, computer)
    show_results(outcome, player, computer)
    new_scores = update_scores(scores, outcome)
    return new_scores


def play_again():
    while True:
        print("\nDo you want to play again?")
        print("(Y)es")
        print("(N)o")
        ans = input("&gt; ").lower()
        if ans == 'y':
            return True
        elif ans == 'n':
            return False


def starting_scores():
    return 0, 0, 0


def main():
    scores = starting_scores()
    still_playing = True
    while still_playing:
        show_statistics(scores)
        scores = rock_paper_scissors(scores)
        still_playing = play_again()


if __name__ == '__main__':
    main()
Firstly, this is some nice clean code. Well done.

The changes I'd make:


win_msg and lose_msg can instead be global constant strings.
You should pick a preferred string delimiter and stick to using just that one. I prefer '.
I would make a function clear_console as the code is rather strange. And will ease use if you need it again.
game_outcome can be simplified by using a dictionary to store what beats what.

This also means you can expand to RPSLS with ease.
show_results can be changed to use a dictionary too.
update_scores can be changed in one of two ways:


Add a dictionary that converts from outcome to the index.
Change scores to a dictionary.



And so you can get the following code:

import os
from random import choice

MESSAGES = {
    'Win': '{player} beats {computer}. You won!',
    'Lose': '{computer} beats {player}. You lost!',
    'Draw': 'Draw. Nobody wins or losses.'
}

BEATS = {
    'Rock': 'Scissors',
    'Paper': 'Rock',
    'Scissors': 'Paper'
}


def player_choice():
    while True:
        print('Rock, paper or scissors?')
        choice = input('&gt;').capitalize()
        if choice in ('Rock', 'Paper', 'Scissors'):
            return choice


def play_again():
    while True:
        print('\nDo you want to play again?')
        print('(Y)es')
        print('(N)o')
        ans = input('&gt; ').lower()
        if ans == 'y':
            return True
        elif ans == 'n':
            return False


def computer_choice():
    return choice(('Rock', 'Paper', 'Scissors'))


def clear_console():
    os.system('cls' if os.name == 'nt' else 'clear')


def game_outcome(player, computer):
    if player == computer:
        return 'Draw'

    if BEATS[player] == computer:
        return 'Win'
    else:
        return 'Lose'


def rock_paper_scissors(scores):
    clear_console()
    print(f'Wins: {scores["Win"]}\nLosses: {scores["Lose"]}\nDraws: {scores["Draw"]}')
    player = player_choice()
    computer = computer_choice()
    outcome = game_outcome(player, computer)
    print(MESSAGES[outcome].format(player=player, computer=computer))
    scores[outcome] += 1
    return new_scores


def main():
    scores = {
        'Win': 0,
        'Lose': 0,
        'Draw': 0
    }
    still_playing = True
    while still_playing:
        scores = rock_paper_scissors(scores)
        still_playing = play_again()


if __name__ == '__main__':
    main()




From here you can look into using enum to remove the strings from your code. This is good because it's easy to make a typo in a string, say I use 'rock' rather than 'Rock'. It also means that if you do make a typo then you'll be able to see where it was made when you reach that code. However with a string it'll move the error to a later part of the code and make debugging horrible.

Here is an example of how you can use them:

from enum import Enum


class Score(Enum):
    WIN = 'Win'
    LOSE = 'Lose'
    DRAW = 'Draw'


MESSAGES = {
    Score.WIN: '{player} beats {computer}. You won!',
    Score.LOSE: '{computer} beats {player}. You lost!',
    Score.DRAW: 'Draw. Nobody wins or losses.'
}