better write rock paper scissors (python) - python

Hey guys I'm new to python and I have made this simple rock paper scissors game but I wonder if there is a better way to program this without a super long if else statement.
import random
options = ["scissors", "paper", "rock"]
i = random.randint(0, (len(options) - 1))
playedHand = input("PLay rock, paper or scissors please: ")
computerPlayedHand = options[i]
if playedHand == "rock" and computerPlayedHand == "scissors":
print("the computer had scissors, you win")
elif playedHand == "rock" and computerPlayedHand == "paper":
print("the computer had paper, you lose")
elif playedHand == "rock" and computerPlayedHand == "rock":
print("the computer also had rock, its a tie")
elif playedHand == "paper" and computerPlayedHand == "rock":
print("the computer had rock, you win")
elif playedHand == "paper" and computerPlayedHand == "scissors":
print("the computer had scissors, you lose")
elif playedHand == "paper" and computerPlayedHand == "paper":
print("the computer also had paper, its a tie")
elif playedHand == "scissors" and computerPlayedHand == "paper":
print("the computer had paper, you win")
elif playedHand == "scissors" and computerPlayedHand == "scissors":
print("the computer also had scissors, its a tie")
elif playedHand == "scissors" and computerPlayedHand == "rock":
print("the computer had rock, you lose")
else:
print("please only state rock, paper or scissors")

Here is what I threw together trying to reuse your code where possible.
The key part is noticing that the options list can be treated as a cycle where an option always beats the next option. You can check this by finding the indices and then using modulo to make the indices cyclic.
import random
options = ["scissors", "paper", "rock"] # everything loses to the previous thing
comp_index = random.randint(0, (len(options) - 1))
playedHand = input("Play rock, paper or scissors please: ")
computerPlayedHand = options[comp_index]
try:
player_index = options.index(playedHand)
except ValueError:
print("please only state rock, paper or scissors")
else:
if player_index == comp_index:
res = "the computer also had {}, its a tie"
# the key part
elif (player_index - comp_index) % 3 == 1:
res = "the computer had {}, you lose"
else:
res = "the computer had {}, you win"
print(res.format(computerPlayedHand))

Using a dictionary to represent which hand beat which can significantly shorten your code. But since we are there, let's make this even neater with an object-oriented solution.
import random
class Hand:
_ordering = {
'rock': 'scissor',
'scissor': 'paper',
'paper': 'rock'
}
def __init__(self, kind):
if kind in self._ordering:
self.kind = kind
else:
raise ValueError(
"It's rock, paper, scissor... Not rock, {}, scissor.".format(kind)
)
#classmethod
def random_hand(cls):
return cls(random.choice(list(cls._ordering)))
def beats(self, other):
return self._ordering[self.kind] == other.kind
playedHand = Hand(input("Play rock, paper or scissors please: "))
computerPlayedHand = Hand.random_hand()
if playedHand.beats(computerPlayedHand):
print('You won! The computer had {}.'.format(computerPlayedHand.kind))
elif computerPlayedHand.beats(playedHand):
print('You lost... The computer had {}.'.format(computerPlayedHand.kind))
else:
print("It's a tie.")

You don't need to use any "if" statements other than typical error management. Look at the following example:
import random
def play():
table = [[2, 0, 1],
[1, 2, 0],
[0, 1, 2]]
options = ["Rock", "Paper", "Scissors"]
results = ["Defeat", "Win", "Tie"]
conv = {"R": 0 , "P": 1, "S": 2}
while True:
i = random.randint(0, (len(options) - 1))
p = input("Play rock, Paper or Scissors please (R, P, S): ")
if p not in conv.keys():
print("Unavailable option. Left the Game.")
return
print("Computer played %s. You have a %s"%(options[i], results[table[conv[p]][i]]))
play()
If you have a table like this:
# Rock Paper Scissor
# Rock 2 0 1
# Paper 1 2 0
# Scissor 0 1 2
...you can make the user play in rows, and the computer in columns. The result is being indexed directly by whatever is the number in the table. Thus playing the game in the example would look like this:

Here's another possible version:
import random
try:
options = [('rock', 'scissors'), ('paper', 'rock'), ('scissors', 'paper')]
human_choice = int(input("Play rock(0), paper(1) or scissors(2) please: "))
human_hand = options[human_choice]
computer_hand = options[random.randint(0, (len(options) - 1))]
text = "the computer {} {}, {}"
if human_hand[0] == computer_hand[0]:
print(text.format("also had", computer_hand[0], "it's a tie"))
elif human_hand[1] == computer_hand[0]:
print(text.format("had", computer_hand[0], "you win"))
else:
print(text.format("had", computer_hand[0], "you lose"))
except Exception as e:
print("please only state rock, paper or scissors")

Related

Rock, paper, scissors game in Python - some clarification needed

I am writing a simple game of rock, paper and scissors, where the user competes with a computer. There are 5 tries.
The problems I ran into are :
If I enter something apart from three options, it should return "Invalid Entry". Instead, the program stops
The program never prints "You won the game" or "You lost the game", it finishes after 5 attempts
Other feedback would also be appreciated
import random
def game():
win_count = 0
loose_count = 0
tries = 0
while tries < 5:
chosen = input("Make your choice: ")
if chosen == "scissors" or chosen == "Scissors":
element = "scissors"
elif chosen == "paper" or chosen == "Paper":
element = "paper"
elif chosen == "rock" or chosen == "Rock":
element = "rock"
else:
return "Invalid Entry"
computer_choices = ["scissors", "paper", "rock"]
computer_choice = random.choice(computer_choices)
if element == "scissors" and computer_choice == "paper":
print("Computer chose paper, you chose scissors, you win !")
win_count += 1
tries += 1
elif element == "paper" and computer_choice == "scissors":
print("Computer chose scissors, you chose paper, you loose !")
loose_count += 1
tries += 1
elif element == "paper" and computer_choice == "rock":
print("Computer chose rock, you chose paper, you win !")
win_count += 1
tries += 1
elif element == "rock" and computer_choice == "paper":
print("Computer chose paper, you chose rock, you loose !")
loose_count += 1
tries += 1
else:
print("Whoops, that's a draw, try again")
tries+=1
print("Your Wins: "+ str(win_count))
print("Computer Wins: "+str(loose_count))
if win_count > loose_count:
return "Congrats, you won the game!"
else:
return "Sorry, you lost"
game()
return statement does not print anything but they return the value from a function and as soon as a return statement executes the function ends up executing that's why whenever the user inputs something invalid the program stop.
Also not use the if statement from if chosen = paper or chosen = Paper instead use .lower() to lower the string.
I have made some changes to your code.
Try this code
import random
def game():
win_count = 0
loose_count = 0
tries = 0
while tries < 5:
element = input("Make your choice: ").lower()
computer_choices = ["scissors", "paper", "rock"]
if element not in computer_choices:
print("Invalid choice")
continue
computer_choice = random.choice(computer_choices)
if element == "scissors" and computer_choice == "paper":
print("Computer chose paper, you chose scissors, you win !")
win_count += 1
tries += 1
elif element == "paper" and computer_choice == "scissors":
print("Computer chose scissors, you chose paper, you loose !")
loose_count += 1
tries += 1
elif element == "paper" and computer_choice == "rock":
print("Computer chose rock, you chose paper, you win !")
win_count += 1
tries += 1
elif element == "rock" and computer_choice == "paper":
print("Computer chose paper, you chose rock, you loose !")
loose_count += 1
tries += 1
else:
print("Whoops, that's a draw, try again")
tries+=1
print("Your Wins: "+ str(win_count))
print("Computer Wins: "+str(loose_count))
if win_count > loose_count:
print("Congrats, you won the game!")
else:
print("Sorry, you lost")
game()

How do I make my basic Rock/Paper/Scissors game with fewer lines of code?

I built this simple rock/paper/scissor game by watching some tutorials. Everything is working fine. The issue is that I want to implement something where if the user and the computer choose the same word, then it should say something like "draw."
I could go ahead and add a bunch of "if" and "else" statements, but I don't want that. Can you guys think of any other way to implement that with fewer lines of code?
#Simple rock, paper and scissor game
import random
user_wins = 0
computer_wins = 0
options = ["rock", "paper", "scissors"]
while True:
user_pick = input("Please choose Rock/Paper/Scissors Or Press Q to quit: ")
if user_pick.lower() == "q":
print("You quit.")
break
elif user_pick not in options:
print("Please enter a valid input.")
continue
random_number = random.randint(0, 2)
computer_pick = options[random_number]
print("The computer picked", computer_pick)
if computer_pick == "rock" and user_pick == "scissors":
print("You lost!")
computer_wins += 1
elif computer_pick == "paper" and user_pick == "rock":
print("You lost!")
computer_wins += 1
elif computer_pick == "scissors" and user_pick == "paper":
print("You lost!")
computer_wins += 1
else:
print('You win!')
user_wins += 1
You could use a dictionary to map which choices beat each other. This will enable to you make the conditional part of the code, which determines who wins, more concise. It is also more easily expanded to rock-paper-scissors variants with more options, without the need for many more conditional statements.
#Simple rock, paper and scissor game
import random
user_wins = 0
computer_wins = 0
options = ["rock", "paper", "scissors"]
beaten_by = {
"rock": "scissors",
"scissors": "paper",
"paper": "rock"
}
while True:
user_pick = input("Please choose Rock/Paper/Scissors Or Press Q to quit: ")
if user_pick.lower() == "q":
print("You quit.")
break
elif user_pick not in options:
print("Please enter a valid input.")
continue
random_number = random.randint(0, 2)
computer_pick = options[random_number]
print("The computer picked", computer_pick)
if user_pick == computer_pick:
print("Draw!")
elif user_pick == beaten_by[computer_pick]:
print("You lost!")
computer_wins += 1
else:
print("You win!")
user_wins += 1

Using getpass to hide user input in terminal

I'm teaching myself python and one of my little starting projects is a Rock, Paper, Scissors game.
The code runs fine. I would like to add an extra feature though. Whenever a user enters Rock, Paper or Scissor the input remains in the terminal. That of course leads to some unfair circumstances for the second player.
In order to try to circumvent this, I'm using the getpass function. Unfortunately, after using getpass with P1inp and P2inp in my code, the input still remains on the terminal. Could anyone point out a better solution or nudge me in the right direction?
import sys
import getpass
rules = "Rules:Rock beats Scissors, Scissors beats Paper, and Paper beats Rock"
print(rules)
print("Would you like to play?")
decision = input("Yes or No?")
P1 = str(input("What's the name of Player 1?"))
P2 = str(input("What's the name of Player 2?"))
P1inp = getpass.getpass(input("%s, Rock, Paper or Scissors?"%P1))
P2inp = getpass.getpass(input("%s, Rock, Paper or Scissors?"%P2))
def play(decision):
if decision == "Yes":
compare(P1inp,P2inp)
else:
print("See you next time!")
def compare(P1inp,P2inp):
if P1inp == P2inp:
print("It's a tie!")
elif P1inp == "Rock" and P2inp == "Scissors":
print("%s wins!!"%P1)
elif P1inp == "Rock" and P2inp == "Paper":
print("%s wins!!"%P2)
elif P1inp == "Paper" and P2inp == "Scissors":
print("%s wins!!"%P2)
elif P1inp == "Paper" and P2inp == "Rock":
print("%s wins!!"%P1)
elif P1inp == "Scissors" and P2inp == "Rock":
print("%s wins!!"%P2)
elif P1inp == "Scissors" and P2inp == "Paper":
print("%s wins!!"%P1)
else:
return("Invalid input")
sys.exit()
print(compare(P1inp,P2inp))
print ("Would you like to play again?")
result = input("Yes or No?")
while result == "Yes":
samePlayers = input("Are P1 and P2 still the same?")
if samePlayers == "Yes":
P1inp = input("%s, Rock, Paper or Scissors?"%P1)
P2inp = input("%s, Rock, Paper or Scissors?"%P2)
play(result)
print(compare(P1inp,P2inp))
print ("Would you like to play again?")
result = input("Yes or No?")
else:
P1 = str(input("What's the name of Player 1?"))
P2 = str(input("What's the name of Player 2?"))
P1inp = input("%s, Rock, Paper or Scissors?"%P1)
P2inp = input("%s, Rock, Paper or Scissors?"%P2)
play(result)
print(compare(P1inp,P2inp))
print ("Would you like to play again?")
result = input("Yes or No?")
else:
print("Thanks for playing!")
In getpass.getpass() you should not also have input because Input asks for plain text.
P1inp = getpass.getpass(("%s, Rock, Paper or Scissors?"%P1))
P2inp = getpass.getpass(("%s, Rock, Paper or Scissors?"%P2))

Python rock, paper, scissors game. not always give correct answers

I'm trying to make a simple Rock, Paper, Scissors game in python 3.4 and it works to a certain degree but some time i get an output of "You Won Rock crushes Rock" even though i thought i have stop this from happening and only allowed certain outcomes of the code with my elif and if statements. So can anyone tell me why isn't this working sometimes. :)
import random
count = 0
OPTIONS = ['rock', 'paper', 'scissors']
# then check if the user lose's, wins ties
def computer():
return random.choice(OPTIONS)
print("\n"+"-=-"*11)
print("Welcome to ROCK, PAPER, SCISSORS")
print(" GAME")
print(" It's you Vs. the computer!")
print("-=-"*11)
while True:
user = input("What do you choose Rock, Paper, Scissors: ").lower()
if user in OPTIONS:
# Possible user time a user can succeeds rock beats sicissor, sicissors cuts paper, paper covers rock
if user == computer():
print("tie")
elif user == 'rock' and computer() == 'scissors':
print("\nYou Won! {} crushes {}".format(user.title(), computer().title()))
elif user == 'scissors' and computer() =='rock':
print("\nComputer Won! {} crushes {}".format(computer().title(), user.title() ))
elif user == 'scissors' and computer() == 'paper':
print("\nYou Won! {} cuts {}".format(user.title(), computer().title()))
elif user == 'paper' and computer() == 'scissors':
print("\nComputer Won! {} cuts {}".format(computer().title(), user.title()))
elif user == 'paper' and computer() == 'rock':
print("\nYou Won! {} covers {}".format(user.title(), computer().title()))
elif user == 'rock' and computer() == 'paper':
print("\nComputer Won! {} covers {}".format(computer().title(), user.title()))
else:
print("\nMake sure you choose ethier Rock, Paper or Scissors")
enter code here
elif user == 'rock' and computer() == 'scissors':
print("\nYou Won! {} crushes {}".format(user.title(), computer().title()))
Every time you call computer(), it generates a completely new value, independent of any previous calls. For example, in the code above it's entirely possible that the first computer() call returns "scissors", and the second one returns "rock".
Call computer() only once in the loop, and store the result. Then use that value for the rest of your code.
while True:
user = input("What do you choose Rock, Paper, Scissors: ").lower()
if user in OPTIONS:
computer_move = computer()
# Possible user time a user can succeeds rock beats sicissor, sicissors cuts paper, paper covers rock
if user == computer_move:
print("tie")
elif user == 'rock' and computer_move == 'scissors':
print("\nYou Won! {} crushes {}".format(user.title(), computer_move.title()))
#etc
Your computer() function calls a random number. So every time you call computer() in you code you are choosing 'at random' a completely new number. Because there are only three answers, you may actually end up with the right answer quite often.
Think of calling the function as rolling a die (with 3 sides, whoa). So now your program looks like this:
def RollDice():
return random.choice(OPTIONS)
#...
while True:
user = input("What do you choose Rock, Paper, Scissors: ").lower()
if user in OPTIONS:
# Possible user time a user can succeeds rock beats scissor, scissors cuts paper, paper covers rock
if user == RollDice:
print("tie")
elif user == 'rock' and RollDice == 'scissors':
print("\nYou Won! {} crushes {}".format(user.title(), RollDice.title()))
elif user == 'scissors' and RollDice =='rock':
print("\nComputer Won! {} crushes {}".format(RollDice.title(), user.title() ))
#...
Now you see what the problem is.What you really want is to save the value of 'one' random choice at the very beginning of your if statement:
if user in OPTIONS:
computerChoice = computer()
if user == computerChoice:
print("tie")
elif user == 'rock' and computerChoice == 'scissors':
print("\nYou Won! {} crushes {}".format(user.title(), computerChoice.title()))
elif user == 'scissors' and computerChoice =='rock':
print("\nComputer Won! {} crushes {}".format(computerChoice.title(), user.title() ))
#....
That way you have one constant choice saved in a variable to call on.
P.S. It would also be better to use raw_input instead of input so that the program will automatically change the users input into a string.
Disclaimer, the answer has been given, this is merely to peak the interest in generalizing the game.
To make any type of Rock-Paper-Scissor game you can realize that it is in fact a round-robin table of wins.
For instance if you do this:
P-R-S..P-R-S
you can see that the previous letter always wins on the next letter.
Using this approach it becomes easy to create custom rock-paper-scissor games using look-around tables:
import random
from collections import OrderedDict
# Important to retain order of "kill"
OPTIONS = OrderedDict([('P', 'Paper'),
('R', 'Rock'),
('S', 'Scissors')])
# N_KILLS determines how many letters in front it is killing
N_KILLS = 1
OPTIONS = OrderedDict([('P', 'Princess'),
('J', 'Knight'),
('W', 'Wizard'),
('D', 'Dragon'),
('K', 'King')])
N_KILLS = 2
# Create lookup table
LOOKUP = OPTIONS.keys()
# Number of items
N_ITEMS = len(LOOKUP)
# Options to choose from
STR_OPTIONS = ' ,'.join( OPTIONS.values() )
def computer():
return random.randint(0,N_ITEMS-1)
print("\n"+"-=-"*11)
print("Welcome to "+STR_OPTIONS)
print(" GAME")
print(" It's you vs. the computer!")
print("-=-"*11)
while True:
# Convert user option to integer
uidx = computer()
if uidx >= 0:
# Get computer index
cidx = computer()
d = cidx - uidx
# Correct for wrap-arounds
if d > N_KILLS:
d = d - N_ITEMS
elif d < -N_KILLS:
d = d + N_ITEMS
print(' You choose: '+OPTIONS[LOOKUP[uidx]] + ' computer chooses: '+OPTIONS[LOOKUP[cidx]])
if d == 0:
print(' Tie ...')
elif d > 0 and d <= N_KILLS:
print(' You WIN ...')
elif d < 0 and -d <= N_KILLS:
print(' You LOOSE ...')
else:
# This will only occur if N_KILLS*2+1<N_ITEMS
print(' Tie ...')
Not only is the code easier to read (in my opinion), but it becomes extremely easy to implement several new games. For instance check this amazing game out: http://www.umop.com/rps101.htm
You almost had it correct, as has been mentioned, for each game, the call to computer() should only be made once. It would also make sense to display the two player's choices. Also as you are working in title case, it would make sense to convert everything to use that to avoid needing to call .title() so many times.
import random
OPTIONS = ['Rock', 'Paper', 'Scissors']
# then check if the user lose's, wins ties
def computer():
return random.choice(OPTIONS)
print("\n"+"-=-"*11)
print("Welcome to ROCK, PAPER, SCISSORS")
print(" GAME")
print(" It's you Vs. the computer!")
print("-=-"*11)
while True:
user_choice = input("\nWhat do you choose Rock, Paper, Scissors: ").title()
computer_choice = computer()
print("User: {} Computer: {}".format(user_choice, computer_choice))
if user_choice in OPTIONS:
# Possible user_choice time a user_choice can succeeds rock beats sicissor, sicissors cuts paper, paper covers rock
if user_choice == computer_choice:
print("tie")
elif user_choice == 'Rock' and computer_choice == 'Scissors':
print("You Won! {} crushes {}".format(user_choice, computer_choice))
elif user_choice == 'Scissors' and computer_choice == 'Rock':
print("Computer Won! {} crushes {}".format(computer_choice, user_choice ))
elif user_choice == 'Scissors' and computer_choice == 'Paper':
print("You Won! {} cuts {}".format(user_choice, computer_choice))
elif user_choice == 'Paper' and computer_choice == 'Scissors':
print("Computer Won! {} cuts {}".format(computer_choice, user_choice))
elif user_choice == 'Paper' and computer_choice == 'Rock':
print("You Won! {} covers {}".format(user_choice, computer_choice))
elif user_choice == 'Rock' and computer_choice == 'Paper':
print("Computer Won! {} covers {}".format(computer_choice, user_choice))
else:
print("Make sure you choose either Rock, Paper or Scissors")
So a game would look like:
-=--=--=--=--=--=--=--=--=--=--=-
Welcome to ROCK, PAPER, SCISSORS
GAME
It's you Vs. the computer!
-=--=--=--=--=--=--=--=--=--=--=-
What do you choose Rock, Paper, Scissors: rock
User: Rock Computer: Scissors
You Won! Rock crushes Scissors

implementing functions in a game

I am having trouble with this part of my assignment. I have to declare a winner of the game and then input into a function. Once I have entered all the if statements I then have to create a function def playGame(). This has to include:
showRules()
user = getUserChoice()
computer = getComputerChoice()
declareWinner(user, computer)
I am not too sure how to do this. Please help.
Below is the code that I have completed so far: (Would I need to do an if statement for scissors as well?)
#Display game rules
print("Rules: Each player chooses either Rock, Paper, or Scissors.")
print("\tThe winner is determined by the following rules:")
print("\t\tScissors cuts Paper --> Scissors wins")
print("\t\tPaper covers Rock --> Paper wins")
print("\t\tRock smashes Scissors --> Rock Wins")
def userchoice():
choice = (input("Make your selection (Rock, Paper, or Scissors). ")).lower()
return choice
#obtain computer input
def getComputerchoice():
import random
rnum = random.randint(1,3)
if rnum == 1:
print("The computer has chosen Rock.")
if rnum == 2:
print("The computer has chosen Paper.")
if rnum == 3:
print("The computer has chosen Scissors.")
return rnum
#Declare winner
def declarewinner (user, rnum):
if userchoice == 1:
print("You have chosen rock.")
if getComputerchoice == 1:
print("Computer has chose rock as well.")
return 0
else:
print("The computer has chosen scissors. Rock breaks scissors. You WIN!")
return 1
if userchoice == 2:
print("You have chosen paper.")
if getComputerchoice == 1:
print("The computer has chosen rock. Paper covers rock. You WIN!")
return 1
elif getComputerchoice == 2:
print("The computer has chosen paper as well.")
return 0
else:
print("The computer has chosen scissors. Scissors cut paper. You LOSE!")
return 1
if userchoice == 3:
print("You have chosen scissors")
if getComputerchoice == 1:
print("The computer has chosen rock. Rock breaks scissors. You LOSE!")
return 1
elif getComputerchoice == 2:
print("The computer has chosen paper. Scissors cut paper. You WIN!")
return 1
how bout
class hand:
def __init__(self,rps):
self.rps = ["rock","paper","scissors"].index(rps.lower())
def __cmp__(self,other): #take advantage of pythons __cmp__ and override it
#this is the magic
wins_against = {0:2,1:0,2:1}
#if their equal return 0
if self.rps == other.rps: return 0
#if this hand wins return 1
if wins_against[self.rps] == other.rps:return 1
#else (This hand loses) return -1
return -1
def __str__(self):
return ["rock","paper","scissors"][self.rps]
print( hand("rock") > hand("paper") )
print( hand("scissors") > hand("paper") )
print( hand("rock") > hand("scissors") )
granted its probably overkill for this but it s a cool technique ... and if you can get it down now it may help you with future assignments
def get_cpu_pick():
return random.choice(["rock", "paper", "scissors"])
def get_player_pick():
valid_inputs = {
'r':'rock','p':'paper','s':'scissors'
}
user_choice = input("Select RPS:")
while user_choice.lower() not in valid_inputs:
user_choice = input("Select RPS:")
return valid_inputs.get(user_choice.lower())
def play():
user_hand = hand(get_player_pick())
cpu_hand = hand(get_cpu_pick())
if user_hand > cpu_hand:
print ("User Wins {0} v. {1}".format(user_hand,cpu_hand))
elif user_hand < cpu_hand:
print ("CPU Wins {0} v. {1}".format(user_hand,cpu_hand))
else:
print("TIE!!!")

Categories

Resources