Rock Paper Scissors function help in Python - python

I just started learning Python, and I am trying to write a basic Rock Paper Scissors program for my assignment. The game is intended to go on for 10 rounds, while keeping track the score between the player and the computer. I have two specific problems with it.
import random
def welcome_prompt():
print ("ROCKER PAPER SCISSORS in PYTHON Assignment")
print ("Rules: Rocks beats Scissors, Scissors beats Paper, Paper beats Rock")
def get_player_move():
print ('Round ' + str(round))
print ("Please play one of the following")
get_player_move = raw_input(" 1) [R]ock, 2) [P]aper, 3) [S]cissors:")
if get_player_move == ("R"):
print ("You used Rock!")
return 1
elif get_player_move == ("P"):
print ("You used Paper!")
return 2
elif get_player_move == ("S"):
print ("You used Scissors!")
return 3
else:
print "Invalid input, please use capitalized initial (R,P,S)"
return get_player_move()
def get_computer_move():
get_computer_move = random.randint(1,3)
if get_computer_move == 1:
print ("Computer used Rock!")
return 1
elif get_computer_move == 2:
print ("Computer used Paper!")
return 2
elif get_computer_move == 3:
print ("Computer used Scissors!")
return 3
def compare_moves(get_player_move, get_computer_move):
# Rock = 1
# Paper = 2
# Scissors = 3
if (get_player_move == 1 and get_computer_move == 1) or (get_player_move == 2 and get_computer_move == 2) or (get_player_move == 3 and get_computer_move == 3):
print ("It's a tie!")
return 0
elif (get_player_move == 1 and get_computer_move == 3) or (get_player_move == 2 and get_computer_move == 1) or (get_player_move == 3 and get_computer_move == 2):
print ("You win the round!")
return 1
elif (get_player_move == 1 and get_computer_move == 2) or (get_player_move == 2 and get_computer_move == 3) or (get_player_move == 3 and get_computer_move == 1):
print ("You lose the round!")
return -1
elif (get_player_move == 4):
print ("You didn't put in correct input, computer gets a free win")
return -1
# Game Program
player_score = 0
comp_score = 0
round = 0
welcome_prompt()
('Round ' + str(round))
while round< 10:
round = round + 1
get_player_move()
get_computer_move()
compare_moves(get_player_move, get_computer_move)
if compare_moves == 1:
player_score = player_score + 1
print 'Player Score'+ str(player_score)
print 'Computer Score'+ str(player_score)
elif compare_moves == -1:
comp_score = comp_score + 1
print 'Player Score'+ str(player_score)
print 'Computer Score'+ str(player_score)
print "Game Over"
Firstly, I can't get the compare_move function to recall the returned values from both get_player_move and get_computer_move. The game can run without any error, but it just skips the comparison/ score component completely. I am still a bit iffy with the basics, so not exactly sure what is missing.
Secondly, in the get_player_move function, when I enter an invalid input (example: blah) to test the raw_input, it gives an error.
Traceback (most recent call last):
File "C:\Python27\Rock Paper Scissors.py", line 85, in <module>
get_player_move()
File "C:\Python27\Rock Paper Scissors.py", line 32, in get_player_move
return get_player_move()
TypeError: 'str' object is not callable
So how do you make a function to asks for the correct raw_input again after entering invalid input, without interrupting the while loop?
Explanation is greatly appreciated, thank you

You have a local variable get_player_move inside the function get_player_move(); you cannot then still use the function name (a global).
Rename the get_player_move local variable.
So, instead of:
get_player_move = raw_input(" 1) [R]ock, 2) [P]aper, 3) [S]cissors:")
use:
move = raw_input(" 1) [R]ock, 2) [P]aper, 3) [S]cissors:")
perhaps.
To get user input, it's best not to rely on recursion, however. The user could hit 'C' forever and then your program would crash with an RuntimeError: maximum recursion depth exceeded. It's easier to use a loop instead:
while True:
move = raw_input(" 1) [R]ock, 2) [P]aper, 3) [S]cissors:")
if move == "R":
print ("You used Rock!")
return 1
# etc.
else:
print "Invalid input, please use capitalized initial (R,P,S)"
Because you return from the function when a correct choice is made, the loop automatically is exited as well. If however you get to the end and Invalid input is printed, the while True loop starts at the top again and the user is asked once more to enter a choice.
Next: although your function returns a choice (an integer), you never store that return value. You must store it where you called the function:
player_move = get_player_move()
computer_move = get_computer_move()
result = compare_moves(player_move, computer_move)
if result == 1:
Note that it's not the function name that holds the return value; it's a separate variable. player_move is assigned whatever the get_player_move() returned, for example.
You can then pass these returned values to compare_moves(); it also returns a result, here stored in result for further comparisons.

Related

Stuck inside the while loop

I was writing code for Rock Paper Scissors game in Python. This is kinda tournament style (3 rounds)
But it just keeps playing after the 3rd round is over.
def play():
player = input("Please type 'r' for Rock, 'p' for Paper and 's' Scissors: \n").lower()
while (player != 'r') and (player != 'p') and (player != 's'):
player = input("That is not an valid option. Please try again:\n").lower()
computer = random.choice(['r', 'p', 's'])
commands = {
"r" : "Rock",
"p" : "Paper",
"s" : "Scissors"
}
if player == computer:
print("It's a draw! Game Over.")
return("Draw")
elif user_win(player, computer):
print(f"You won! The computer used {commands[computer]} against your {commands[player]} and lost.")
return("Won")
print(f"You lost! The computer used {commands[computer]} against your {commands[player]} and won.")
return("Lost")
def user_win(player, computer):
# r > s, s > p and p > r
if (player == 'r' and computer == 's') or (player == 's' and computer == 'p') or (player == 'p' and computer == 'r'):
return True
print("Hello, Player! Choose your weapon.")
count, user, comp = 0, 0, 0
while count < 3:
count =+ 1
outcome = play()
if outcome == 'Won':
user =+ 1
elif outcome == 'Lost':
comp =+ 1
if user > comp:
print(f"You win. You: {user} Computer: {comp}")
elif comp > user:
print(f"You lost. You: {user} Computer: {comp}")
else:
print(f"Its a draw. You: {user} Computer: {comp}")
This is the full code. Below is the part which have problem (if i understood it right)
while count < 3:
count =+ 1
outcome = play()
if outcome == 'Won':
user =+ 1
elif outcome == 'Lost':
comp =+ 1
Ps: This is my first time posting on stackoverflow so sorry if i posted in wrong way.
The error is count =+ 1. Try count += 1, that should work.
(As a little background: count =+ 1 will simply assign a value of 1 to the variable count. After that, count never chnages, so it can never reach 3, and you're stuck in an infinite loop. The increment you want is count += 1.)
When you do
count =+1, it just assigns the value +1 to variable count, which is less than the required exit value of 3. You can try to log the value of count across iterations for a better understanding.
Fix:
Change the =+ to += for what I suppose is your requirement, ie to increment value by 1 on each iteration. Read through What is the difference between '+=' and '=+'?

How to make a function to score a Rock, Paper and Scissor game in Python?

I wrote a Rock, Paper and Scissor game in Python. And I want to have a function that scores the game. The only way I managed to do that was by using global variables inside the function. I know that's not a good practice and I'd like to know how can I make this function without the need for global variables.
import random
def validate_user_input(input):
"""Verify if user input is a valid."""
try:
usr_input = int(input)
except:
return 0
else:
if (usr_input >= 1) and (usr_input <= 3):
return usr_input
else:
return 0
def compare_results(player_choice):
"""Get computer choice and compare it with user choice"""
computer_option = random.randint(1,3)
result_to_word = {0:'- Draw', 1:'- You loose.', 2:'- You Win'}
if player_choice == computer_option:
result = 0
if (player_choice == 1 and computer_option == 2):
result = 1
if (player_choice == 1 and computer_option == 3):
result = 2
if (player_choice == 2 and computer_option == 1):
result = 2
if (player_choice == 2 and computer_option == 3):
result = 1
if (player_choice == 3 and computer_option == 1):
result = 1
if (player_choice == 3 and computer_option == 2):
result = 2
return (result, result_to_word[result], computer_option)
def codify_result(input):
"Transform number of choice into word"
num_to_word = {1: "Rock", 2: "Paper", 3:"Scissor"}
return num_to_word[input]
def make_score(result):
global computer_score
global player_score
if result == 1:
computer_score += 1
elif result == 2:
player_score += 1
player_score = 0
computer_score = 0
intro = "\nHello!\nLet's play 'Rock, Paper and Scissors'.\nChoose an option and wait to see the result (Press 'q' at any time to exit)"
print(intro)
while True:
user_input = input("\n1) Rock, 2) Paper os 3) Scissors?: ")
if (user_input == 'q'):
break
else:
user_choice = validate_user_input(user_input)
if user_choice == 0:
print("You have to choose a number between 1 and 3.")
else:
result = compare_results(user_choice)
print("You chose: " + codify_result(user_choice) + ".")
print("The computer chose: " + codify_result(result[2]) + '.')
print(result[1])
make_score(result[0])
print("You: " + str(player_score) + "\nComputer: " + str(computer_score))
So how could I implement this function in a better way?
A "pure functional" approach could be to change your make_score function to take the old scores as arguments, and then return the updated scores:
def make_score(result, computer_score, player_score):
if result == 1:
computer_score += 1
elif result == 2:
player_score += 1
return computer_score, player_score
When you call make_score you pass the old scores and assign the new scores:
computer_score, player_score = make_score(result[0], computer_score, player_score)
Taking a step back, though, I might suggest taking an approach that doesn't require you to have a function that translates an opaque result int value into a modification to one or another variable. Maybe put the scores in a dict:
scores = {
"computer": 0,
"player": 0,
}
and then instead of a magic result int, assign a winner that matches one of the dict keys:
if (player_choice == 1 and computer_option == 2):
winner = "computer"
and then you can get rid of the make_score function completely and just do:
scores[winner] += 1
I would recommend making a dictionary which you can then pass into make_score
score_dict = {'computer_score': 0, 'player_score': 0}
make_score(score_dict, result):
if result == 1:
score_dict['computer_score'] += 1
...

Python: Rock Paper Scissors While Loop Issue

I'm having an issue with my programming of Rock, Paper, Scissors for Python. My issue occurs when there is a tie. When there is a tie, my program is supposed to going into a while loop within the if statement of the tie and reask the player the same question, rock, paper or scissors again until it breaks out of the tie. I have attached the link to the image of the issue:
In Round 5: you can see the issue.
I am taking an intro to programming class so I'm still a beginner and I do not know what I am doing wrong.
A Python program for the Rock, Paper, Scissors game.
import random
def rock_paper_scissors():
playerscore = 0
computerscore = 0
rounds = input('\nHow many points does it take to win?: ')
count = 1
while playerscore or computerscore != int(rounds):
print('\n********************* ROUND #',count,'*********************')
player = input('\nPick your throw: [r]ock, [p]aper, or [s]cissors?: ')
computerthrow = random.randint(0,2)
if (computerthrow == 0):
computer = "rock"
computer = 'r'
elif (computerthrow == 1):
computer = "paper"
computer = 'p'
elif (computerthrow == 2):
computer = "scissors"
computer = 's'
if (player == computer):
print('Tie!')
while (player == computer):
player = input('\nPick your throw: [r]ock, [p]aper, or [s]cissors?: ')
computerthrow = random.randint(0,2)
if (computerthrow == 0):
computer = "rock"
computer = 'r'
elif (computerthrow == 1):
computer = "paper"
computer = 'p'
elif (computerthrow == 2):
computer = "scissors"
computer = 's'
print(computer)
elif (player == 'r'):
if (computer == "p"):
print('Computer threw paper, you lose!')
computerscore=computerscore+1
else:
print('Computer threw scissors, you win!')
playerscore = playerscore+1
#count = count + 1
elif (player == 'p'):
if (computer == "r"):
print('Computer threw rock, you win!')
playerscore = playerscore+1
else:
print('Computer threw scissors, you lose!')
computerscore=computerscore+1
#count = count + 1
elif (player == 's'):
if (computer == "p"):
print('Computer threw paper, you win!')
playerscore = playerscore+1
else:
print('Computer threw rock, you lose!')
computerscore=computerscore+1
count = count + 1
print('\nYour score: ',playerscore)
print('Computer''s score: ',computerscore,'\n')
print('********************* GAME OVER ********************')
def main():
print('ROCK PAPER SCISSORS in Python')
print()
print('Rules: 1) Rock wins over Scissors.')
print(' 2) Scissors wins over Paper.')
print(' 3) Paper wins over Rock.')
rock_paper_scissors()
main()
Your problem comes from the way you have structured your control statements (if, elif, else). When you enter your tie while loop, you are constantly running it until someone wins and that looks like it works no problem. The issue is that once you do that, the python interpreter skips all elif and else statements in that control block (if I say if x == 3: do this else: do that) I don't want python to follow through with the else condition if x does indeed == 3). Sorry if that is confusing, long story short you need to make sure that even when your tie block gets executed you still move on to scoring the round and starting a new one. The easy way to do that is just change the elif (player == "r") to an if statement. That way the interpreter treats the scoring control sequence as its own block and it will always be executed once you assign the throws each player makes.
Example:
def f(x):
if (x == 0):
print("1")
x += 1
elif (x == 1):
print("2")
print("Done!")
def g(x):
if (x == 0):
print("1")
x += 1
if (x == 1):
print("2")
print("Done!")
if you call f(0):
Python will print out 1 and then Done!
if you call g(0):
Python will print out 1 then 2 then Done!
Your immediate problem is that you have the handling code for a tie in the same if/elif chain as the handling for the other scoring.
You say something like:
if tied
stuff
elif player == r
...
As a result, when there is a tie the game correctly loops until there is no tie. But then is skips over the code that updates the score, because that is how if/elif/else works!
An immediate fix would be to break that if/elif chain, and put the tie-handling into a separate if block:
if tied:
loop until not tied
# now do scoring
if player == 'r':
... etc
With that said, let me add a few more things:
You are assigning two values to the same variable, in sequence:
computer = 'rock'
computer = 'r'
This doesn't do anything, because the second overwrites the first. You should just delete the first line in each of those pairs.
You should probably write a function that repeatedly asks the user to pick one, until it gets either rock, paper, or scissors. Use a while loop.
There is a function in the random module that will pick an item from a list, tuple, or string and return it. You can use that to make the computer pick r,p,s directly.
You can simplify your code by determining the outcome in advance. Say you have the computer pick first. Then if the computer picks 'r', you know 'p' is a win and 's' is a lose. Store the win/lose picks in a pair of variables, and all your testing can be boiled down to one test:
computer = computer_pick()
if computer == 'r':
winner = 'p'
computer = 'rock'
elif computer == 'p':
...
player = player_pick()
if tied ...
if player == winner:
print("Computer picked", computer, "- you win!")
else:
...

Rock Paper Scissors Program Not Working (Python)

Problems:
Program does not seem to accept the integers entered. Won't add to win/loss/draw count and does not display computer choice in debug mode
Basics Design of the Program:
Write a program that lets the user play the game of Rock, Paper, Scissors against the computer.
The program should work as follows.
A menu is displayed:
Score: 0 wins, 0 draws, 0 losses
(D)ebug to show computer's choice
(N)ew game
(Q)uit
If the user enters "Q" or "q" the program would end. "N" or "n" for a new game, "D" or "d" for debug mode, anything else would cause an error message to be displayed.
When a game begins, a random number in the range of 1 through 3 is generated. If the number is 1, then the computer has chosen rock. If the number is 2, then the computer has chosen paper. If the number is 3, then the computer has chosen scissors. (Don't display the computer's choice yet unless we are in "D"ebug mode.)
The user enters his or her choice of “1-rock”, “2-paper”, or “3-scissors” at the keyboard.
The computer's choice is displayed.
A winner is selected according to the following rules:
• If one player chooses rock and the other player chooses scissors, then rock wins.
(The rock smashes the scissors.)
• If one player chooses scissors and the other player chooses paper, then scissors wins.(Scissors cuts paper.)
• If one player chooses paper and the other player chooses rock, then paper wins.
(Paper wraps rock.)
• If both players make the same choice, the game is a draw.
Your program would keep a running total of the number of wins, loses and draws.
Re-display the menu and repeat the game loop.
My Program:
import random
def main():
continuing = "y"
win = 0
lose = 0
draw = 0
while continuing == "y":
print("Score:", win,"wins,", draw, "draws,", lose,"losses")
print("(D)ebug to show computer's choice")
print("(N)ew game")
print("(Q)uit")
choice = input(" ")
if choice == "n" or choice == "N":
win, draw, lose = playgame(win, draw, lose)
elif choice == "d" or choice == "D":
win, draw, lose = playgame2(win, draw, lose)
elif choice == "q" or choice == "Q":
break
def playgame(win, draw, lose):
computer = random.randint(1,3)
player = input("Enter 1 for Rock, 2 for Paper, or 3 for Scissors: ")
if computer == 1 and player == 2:
Score = "You won"
win += 1
elif computer == 1 and player == 3:
Score = "You lost"
lose += 1
elif computer == 2 and player == 1:
Score = "You lost"
lose += 1
elif computer == 2 and player == 3:
Score = "You won"
win += 1
elif computer == 3 and player == 1:
Score = "You won"
win += 1
elif computer == 3 and player == 2:
Score = "You lost"
lose += 1
elif computer == player:
Score = "Draw"
draw += 1
return (win, draw, lose)
def playgame2(win, draw, lose):
computer = random.randint(1, 3)
player = input("Enter 1 for Rock, 2 for Paper, or 3 for Scissors: ")
if computer == 1 and player == 2:
Score = "You won"
print("Computer chose rock")
win += 1
elif computer == 1 and player == 3:
Score = "You lost"
print("Computer chose rock")
lose += 1
elif computer == 2 and player == 1:
Score = "You lost"
print("Computer chose paper")
lose += 1
elif computer == 2 and player == 3:
Score = "You won"
print("Computer chose paper")
win += 1
elif computer == 3 and player == 1:
Score = "You won"
print("Computer chose scissors")
win += 1
elif computer == 3 and player == 2:
Score = "You lost"
print("Computer chose scissors")
lose += 1
elif computer == player:
Score = "Draw"
print("Computer chose the same as you")
draw += 1
return (win, draw, lose)
main()
I'm no Pythonista, but at a guess, input returns strings, and you'll need to convert to integer before comparing to the computer's int.
I also think you are missing a trick in DRYing up your code - you should be able to have a single playgame method, which takes an additional boolean parameter debugmode, which instead of calling print directly, calls an indirection, e.g.:
def debugPrint(debugString, debugMode)
if debugMode
print(debugString)
Hope this makes sense?
This would work in Python 2.x, but, not in Python 3.x
In Python 3.x, input() returns strings. Thus, the player's input would be of the form "1" or "2" or "3". Since 1 and "1" are different, the program will not execute any of the lines in the if and elif blocks in playgame() and playgame2().
Here is a Python 3.x example:
>>> a = input("Input = ")
Input = 1
>>> print a
SyntaxError: Missing parentheses in call to 'print'
>>> print(a)
1
>>> a
'1'
>>> type(a)
<class 'str'>
Thus, you should use i = int(input("Input = ")) wherever you want an integer input.
However, in Python 2.x, input() will take 1 as 1 itself and not as "1". But, when you want to type a string as an inpu, you will have to give the quotes also. Here is an exxample:
>>> a1 = input("Input = ")
Input = 1
>>> a1
1
>>> type(a1)
<type 'int'>
>>> #I want to input a string now:
>>> a2 = input("Input = ")
Input = string
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
a2 = input("Input = ")
File "<string>", line 1, in <module>
NameError: name 'string' is not defined
>>> a2 = input("Input = ")
Input = "string"
>>> a2
'string'
>>> type(a2)
<type 'str'>
>>> a3 = raw_input("Input = ")
Input = hello
>>> a3
'hello'
>>> type(a3)
<type 'str'>
>>>
In Python 2.x, the raw_input() function takes the input as a string.

Simple Rock Paper Scissors game, problems with returning score?

I'm writing this Rock Paper Scissors program for my Programming class, and having some problems getting the full score to show up at the end of the program. I'm super beginner in Python, so nothing too fancy here. For some reason, as I run the program, the only score that shows up is 1 regardless of how many times the game loops. What am I doing wrong here?
from myro import *
from random import *
def announceGame():
""" Announces the game to the user """
speak("Welcome to Rock, Paper, Scissors. I look forward to playing you.")
def computerMove():
""" Determines a random choice for the computer """
randomNumber = random()
if randomNumber == 1:
compMove = "R"
elif randomNumber == 2:
compMove = "P"
else:
compMove = "S"
return compMove
def userMove():
""" Asks the user to input their choice."""
userChoice = raw_input("Please enter R, P, or S: ")
return userChoice
def playGame(userChoice, compMove):
""" Compares the user's choice to the computer's choice, and decides who wins."""
global userWin
global compWin
global tie
userWin = 0
compWin = 0
tie = 0
if (userChoice == "R" and compMove == "S"):
userWin = userWin + 1
print "You win."
elif (userChoice == "R" and compMove == "P"):
compWin = compWin + 1
print "I win."
elif (userChoice == "S" and compMove == "R"):
compWin = compWin + 1
print "I win."
elif (userChoice == "S" and compMove == "P"):
userWin = userWin + 1
print "You win"
elif (userChoice == "P" and compMove == "S"):
compWin = compWin + 1
print "I win"
elif (userChoice == "P" and compMove == "R"):
userWin = userWin + 1
print "You win"
else:
tie = tie + 1
print "It's a tie"
return compWin, userWin, tie
def printResults(compWin, userWin, tie):
""" Prints the results at the end of the game. """
print " Rock Paper Scissors Results "
print "------------------------------------"
print "Computer Wins: " + str(compWin)
print "User Wins: " + str(userWin)
print "Ties: " + str(tie)
def main():
announceGame()
for game in range(1,6):
u = userMove()
c = computerMove()
game = playGame(u,c)
printResults(compWin, userWin, tie)
main()
Inside playGame, you set userWin, compWin, and tie to zero. So every time you call that function, they get set to zero before the new values are added. You should initialize these variables outside the function that you are calling in the loop. (For instance, you could initialize them in announceGame.)

Categories

Resources