0

I have to write a program game similar to rock paper scissors, but with five options instead of three. I was able to write the code with a system of ifs, but I would like to know if there is a better way to write the code.

Game rules:

As you can see, there are a total of 5 options (X → Y means X wins over Y):

  1. Rock → Lizard & Scissors
  2. Paper → Rock & Spock
  3. Scissors → Paper & Lizard
  4. Lizard → Spock & Paper
  5. Spock → Scissors & Rock

Main Code:

import random
from ex2_rpsls_helper import get_selection

def rpsls_game():
  com_score = 0
  player_score = 0
  draws = 0
  while(abs(com_score - player_score) < 2):
    print("    Please enter your selection: 1 (Rock), 2 (Paper), 3 (Scissors), 4 (Lizard) or 5 (Spock): ")
    selection = int(input())
    # a while loop to make sure input i between 0<x<6
    while(selection <= 0 or selection > 5):
        print(    "Please select one of the available options.\n")
        selection = int(input())
    com_selection = random.randint(1,5)
    print("    Player has selected: "+get_selection(selection)+".")
    print("    Computer has selected: "+get_selection(com_selection)+".")

    # A set of else and elseif to determin who is the winner
    if(give_winner(selection, com_selection)):
        print("    The winner for this round is: Player\n")
        player_score += 1
    elif(give_winner(com_selection,selection)):
        print("    The winner for this round is: Computer\n")
        com_score += 1
    else:
        print("    This round was drawn\n")
        draws += 1

    print("Game score: Player "+str(player_score)+", Computer "+str(com_score)+", draws "+str(draws))
  if(player_score > com_score):
    return 1
  else:
    return -1

The IFS system:

def give_winner(first_selection, second_selection):
    if(first_selection is 1):
        if(second_selection is 3 or second_selection is 4):
            return True
    elif(first_selection is 2):
        if(second_selection is 1 or second_selection is 5):
            return True
    elif(first_selection is 3):
        if(second_selection is 2 or second_selection is 4):
            return True
    elif(first_selection is 4):
        if(second_selection is 2 or  second_selection is 5):
            return True
    elif(first_selection is 5):
        if(second_selection is 3 or second_selection is 1):
            return True
    return False

Any ideas?

1
  • 5
    Don't compare values with is. Even if that usually works with integers in the range from -5 to 255, it is not correct. You are not interested on if you have the same object, but if they have the same value. Thus, use ==. Commented Oct 25, 2013 at 8:12

6 Answers 6

5

Instead of a complicated series of if statements, you could have an list or dictionary of (first, second) tuples,

a = [(1,3), (1,4), (2,1), (2,5) ...]

def give_winner(first_selection, second_selection):
    return (first_selection, second_selection) in a

You could also use a frozenset to improve performance.

Sign up to request clarification or add additional context in comments.

Comments

4

You could use a dictionary.

dictionary = {
    1: [3, 4],
    2: [1, 5],
    3: [2, 4],
    4: [2, 5],
    5: [3, 1]
}

def give_winner(first_selection, second_selection):
    if dictionary.has_key(first_selection):
        if second_selection in dictionary[first_selection]:
            return True
    return False

3 Comments

You are re-creating the dictionary every time here, which is unnecessary
BTW You can simply say first_selection in dictionary instead of .has_key.
@Kos and indeed, first_selection in dictionary is preferred - has_key is long since deprecated, and no longer exists in Python 3. It would be even better to skip the check entirely, just do return second_selection in dictionary[first_selection] and possibly catch any KeyError up in the user interaction code.
0

give winner alternative also:

def give_winner(first_selection, second_selection):
    rules = {
        1: lambda x: x in (3, 4),
        2: lambda x: x in (1, 5),
        3: lambda x: x in (2, 4),
        4: lambda x: x in (2, 5),
        5: lambda x: x in (3, 1)
    }
    return rules[first_selection](second_selection)

2 Comments

@aIKid In general, I disagree: lambdas are not unreadable per se. But here, they are overhead. This approach seems better to me.
well, now seeing the other solutions, I vote for those as well.. would like to ask the OP to change the accepted answer.
0

You can make use of classes in python. For example, you can make player as a class with the following attributes:-

    Score
    Name
    OptionChosen

etc similarly, you can make methods like

    UpdateScore()
    DeclareWinner()

etc. This way your program will feel more "neat". You can also make a main() function which contains a

    while True:

and put all your content there. for ex

    class Player:
        def __init__(self,name, score = 0):
          self.name = name
          self.score = score  # initially score is zero
        def ChooseOption(self, name):
           if name == "computer":
            # select choice randomly code
           else:
             var = int(input("Enter choice: "))
        def UpdateScore(self):
            self.score += 1
    def main():
        player1 = Player("Name")
        player2 = Player("Computer") 
        while True:
         resp1 = player1.ChooseOption()
         resp2 = player2.ChooseOption()
         # add other code to manipulate resp1 and resp2 here 

and similarly you can code other things, Hope this gives you some idea

1 Comment

Don't name functions and methods with CamelCase, or with caps at all. Use choose_option, update_score, etc. See PEP 8.
0

I enjoyed building my own little version of Rock Paper Scissor Lizard Spock.

You started your post by explaining som rules. So i figured, why not incorporate the rules inside the code. And i wanted to use real words instead of numbers since it would be easier to understand. But i agree it would be a hassle to spell scissors correct everytime, so i wanted numbers to work as input as well.

from random import randint

# ex. scissors and lizard is beaten by rock
beaten_by = {'rock': ['scissors', 'lizard'],
             'paper': ['rock', 'spock'],
             'scissors': ['paper', 'lizard'],
             'lizard': ['spock', 'paper'],
             'spock': ['scissors', 'rock']}

def rplsls_game():
    player_score, computer_score = 0, 0
    weapons = ['rock', 'paper', 'scissors', 'lizard', 'spock']

    while(abs(player_score - computer_score) < 2):

        print "-----------------------------------------------------------"
        print " Please enter your selection: "
        print " 1 (Rock), 2 (Paper), 3 (Scissors), 4 (Lizard) or 5 (Spock)"

        computer_weapon = weapons[randint(0, 4)]
        weapon = raw_input()
        if weapon in '12345': weapon = weapons[int(weapon) - 1]
        if weapon not in weapons:
            print "invalid input"
            continue        
        print "You selected: " + weapon
        print "Computer selected: " + computer_weapon

        if computer_weapon in beaten_by[weapon]:
            print "You won!"
            player_score += 1
        elif weapon in beaten_by[computer_weapon]:
            print "Computer won!"
            computer_score += 1
        else:
            print "Draw!"

        print "Player: " + str(player_score)
        print "Computer: " + str(computer_score)

    if player_score > computer_score:
        print "Congratulations! you won the game"
    else:
        print "Computer won the game..."

rplsls_game()

Comments

-1

You can use also raw_input instand:

print("    Please enter your selection: 1 (Rock), 2 (Paper), 3 (Scissors), 4 (Lizard) or 5 (Spock): ")
selection = int(input())

try:
  selection = input("Please enter your selection: 1 (Rock), 2 (Paper), 3 (Scissors), 4 (Lizard) or 5 (Spock): ")
except ...

You complete forgot about exceptions.

And if stemtmants in your give_winner function is too large, use dictionar or lambda function.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.