Global variable can't be modified in a separate function - python

I am trying to make a simple RPS game and can't see what I am doing wrong.
I declase pc_choise, player_choice and turn as global variables but I can't modify them in functions such as checkWinner().
If I print that value after the function has been called, it still has the initial value.
Code:
import random
import sys
pc_choices = ['r','p','s']
pc_choise = ''
player_choice = ''
turns = 0
print("\t\tWelcome to Rock Paper Scissors")
def getPcChoice():
return random.randint(1,3) - 1
def getUserChoice():
player_choice = input('Please choose: ')
turns = 1
if(player_choice.lower() not in pc_choices):
print('\nPlease use R, P, or S - *not case sensitive*\n')
getUserChoice()
else:
pc_choise = pc_choices[getPcChoice()]
print('\nYou picked ' + player_choice + ' and the PC picked ' +
pc_choise)
checkWinner()
def checkWinner():
if(player_choice.lower() == pc_choise.lower()):
print('Tie')
elif(player_choice.lower() == 'r' and pc_choise.lower() == 'p'
or player_choice.lower() == 'p' and pc_choise.lower() == 's'
or player_choice.lower() == 's' and pc_choise.lower() == 'r'):
print('You win! 😍')
else:
print('You lose! 🤯')
getUserChoice()

add the following code in the first line of the code:
global pc_choices and global pc_choice etc.
this is to mark the variable will use is a global variable.

You need to declare the variables as global within the function scope so that Python interpreter can interpret them accordingly, otherwise, they get the function scope by default. I also found indentation issues which I have fixed. Below is your modified code:
import random
import sys
pc_choices = ['r','p','s']
pc_choise = ''
player_choice = ''
turns = 0
print("\t\tWelcome to Rock Paper Scissors")
def getPcChoice():
return random.randint(1,3) - 1
def getUserChoice():
global pc_choise
global player_choice
player_choice = input('Please choose: ')
turns = 1
if(player_choice.lower() not in pc_choices):
print('\nPlease use R, P, or S - *not case sensitive*\n')
getUserChoice()
else:
pc_choise = pc_choices[getPcChoice()]
print('\nYou picked ' + player_choice + ' and the PC picked ' + pc_choise)
checkWinner()
def checkWinner():
global pc_choise
global player_choice
if(player_choice.lower() == pc_choise.lower()):
print('Tie')
elif(player_choice.lower() == 'r' and pc_choise.lower() == 'p'
or player_choice.lower() == 'p' and pc_choise.lower() == 's'
or player_choice.lower() == 's' and pc_choise.lower() == 'r'):
print('You win! 😍')
else:
print('You lose! 🤯')
getUserChoice()
However, as suggested by #mario_sunny in the comments, it's better to avoid using global variables.

Related

If statement only showing else portion

I'm writing code for a rock, paper, scissors game but the if statement in the function identify_winner is not running. The only thing that prints out is the else statement and it prints out for all outcomes, not just when it's a tie. I'm pretty sure it has something to do with the variables but I don't know what it is.
import random
ROCK = 1
PAPER = 2
SCISSORS = 3
def main():
user_choose(None)
comp_choose(None)
identify_winner()
def user_choose(weapon):
weapon = int(input('Choose Your Weapon' + '\n (Rock = 1, Paper = 2' +\
' Scissors = 3): '))
if weapon == 1:
print('You have chosen Rock')
elif weapon == 2:
print('You have chosen Paper')
elif weapon == 3:
print('You have chosen Scissors')
def comp_choose(choice):
if random.randint(1,3) == 1:
choice = 'Rock'
elif random.randint(1,3) == 2:
choice = 'Paper'
else:
choice = 'Scissors'
print('Your enemy has chosen',choice)
def identify_winner():
user = 0
comp = 0
while user == comp:
user_choose(user)
comp_choose(comp)
if (user == 1 and comp == 3) or (user ==2 and comp == 1) or (user == 3 and comp
== 2):
print('Congratulations! You have defeated the foe!')
elif (comp ==1 and user == 3) or (comp == 2 and user == 1) or (comp == 3 and
user == 2):
print('Alas, you have been defeated! Better luck next time!')
else:
print('Oh no, a tie! choose again!')
main()
First and foremost it is not a good practice to call main function directly as it was a script. If you plan to create not script program you should scope main function inside.
if __name__ == "__main__":
main()
Secondly, you don't need to call user_choose and comp_choose inside identify winner, you can just return those values in your main program and give them as arguments to your identify winner function. Also you should not generate two times a random number in your comp_choose() because in the second elif you could generate the previous number so comp choice most likely be Scissors. I give you one possible solution to your problem:
import random
ROCK = 1
PAPER = 2
SCISSORS = 3
def main():
identify_winner(user_choose(), comp_choose())
def user_choose():
weapon = int(input('Choose Your Weapon' + '\n (Rock = 1, Paper = 2' +\
' Scissors = 3): '))
if weapon == 1:
print('You have chosen Rock')
elif weapon == 2:
print('You have chosen Paper')
elif weapon == 3:
print('You have chosen Scissors')
return weapon
def comp_choose():
comp_weapon = random.randint(1,3)
if comp_weapon == 1:
choice = 'Rock'
elif comp_weapon == 2:
choice = 'Paper'
else:
choice = 'Scissors'
print('Your enemy has chosen',choice)
return comp_weapon
def identify_winner(user, comp):
if (user == 1 and comp == 3) or (user ==2 and comp == 1) or (user == 3 and comp
== 2):
print('Congratulations! You have defeated the foe!')
elif (comp ==1 and user == 3) or (comp == 2 and user == 1) or (comp == 3 and
user == 2):
print('Alas, you have been defeated! Better luck next time!')
else:
print('Oh no, a tie! choose again!')
if __name__ == "__main__":
main()
I made some little changes in your code. Commented the parts for explanation:
import random
# you never use those, so they are not needed here:
# ROCK = 1
# PAPER = 2
# SCISSORS = 3
def user_choose(): # no input argument needed since you define weapon in the next line anyway
weapon = int(input('Choose Your Weapon' + '\n (Rock = 1, Paper = 2' +\
' Scissors = 3): '))
# this part is asking for a number as long as user don't choose a valid number between 1 and 3.
# You could do even more here, check for number or letter, check if number is 0 or negative
while weapon>3:
weapon = int(input('No valid number. Please choose again: ' + '\n (Rock = 1, Paper = 2' +\
' Scissors = 3): '))
if weapon == 1:
print('You have chosen Rock')
elif weapon == 2:
print('You have chosen Paper')
elif weapon == 3:
print('You have chosen Scissors')
return weapon # you need to return the variable weapon, otherwise it is only in the local scope and your main function doesn't have access to it
def comp_choose(): # same as in the other function, no input argument needed
choice = random.randint(1,3) # in your code random.randint(1,3) executes twice and can have two different results. You want it once and then check on it
if choice == 1:
chose = 'Rock' # in the main() func you compare the numbers, but in your code user has numbers between 1 and 3 and comp has values with rock, paper, scissors.
elif choice == 2:
chose = 'Paper'
else:
choice = 3
chose = 'Scissors'
print('Your enemy has chosen',chose)
return choice # same as in the other function with 'weapon'
def main(): # identy_winner() isn't needed. two functions for user and comp with the main to select winner is enough
run = True
while run: # doing it like this you can make the user choose if he wants to continue or not (later at the 'continue_playing' part)
user = user_choose() # get access to the return value of the function
comp = comp_choose() # get access to the return value of the function
if (user == 1 and comp == 3) or (user ==2 and comp == 1) or (user == 3 and comp
== 2):
print('Congratulations! You have defeated the foe!')
elif (comp ==1 and user == 3) or (comp == 2 and user == 1) or (comp == 3 and
user == 2):
print('Alas, you have been defeated! Better luck next time!')
else:
print('Oh no, a tie! choose again!')
continue_playing = input('You want to play again? [y/n]: ')
if continue_playing == 'n':
run = False
main()
The code will crash if the user chooses a letter instead of numbers, and working poorly if he chooses numbers 0 or less. You may want to check for that.... I leave that up to you.

scissors paper stone game without the use of list in python

im new to this python program and was tasked to generate a game or scissors paper stone game in python without the use of a list. i have the function here as:
def getRandomShape():
Shape = random.randint(1, 3)
if Shape == 1:
print('Scissors'.upper())
elif Shape == 2:
print('Stone'.upper())
else:
print('Paper'.upper())
getRandomShape()
but whenever i call for the function, it says its not defined.
the error occurse at the possibleHands section where im unable to call for the function but able to at the bottom for the checkForWinner function call
here's the full program.
import random
print('welcome to scissors paper stone')
cpuScore = 0
playerScore = 0
tieScore = 0
possibleHands = getRandomShape(computerHand)
def getRandomShape(computerHand):
Shape = random.randint(1, 3)
if Shape == 1:
print('Scissors'.upper())
elif Shape == 2:
print('Stone'.upper())
else:
print('Paper'.upper())
def checkForWinner(playerHand, computerHand):
if(playerHand == 'Stone' and computerHand == 'Paper'):
print('you lost')
return 'cpu'
elif(playerHand == 'Stone' and computerHand == 'Scissors'):
print('you won')
return 'player'
elif(playerHand == 'Scissors' and computerHand == 'Paper'):
print('you won')
return 'player'
elif(playerHand == 'Scissors' and computerHand == 'Stone'):
print('you lost')
return 'cpu'
elif(playerHand == 'Paper' and computerHand == 'Scissors'):
print('you lost')
return 'cpu'
elif(playerHand == 'Paper' and computerHand == 'Stone'):
print('you won')
return 'player'
else:
print('its a tie. play again')
return 'tie'
while(playerScore != 3 and cpuScore != 3):
name = input('Please enter your name: ')
while True:
playerHand = (input('Round 1: '+str(name)+ ', please choose a shape:'))
if(playerHand == 'Scissors' or playerHand == 'Paper' or playerHand == 'Stone'):
break
else:
print('invalid input, case sensitive. Try again')
computerHand = random.choice(possibleHands)
print('your Hand: ', playerHand)
print('cpu Hand: ', computerHand)
results = checkForWinner(playerHand, computerHand)
if(results == 'player'):
playerScore += 1
elif(results == 'cpu'):
cpuScore += 1
else:
tieScore += 1
print('your score: ', playerScore, 'CPU: ', cpuScore, 'Ties: ', tieScore)
print('gg game over')
got this from a youtube tutorial
You must declare the function before its usage. On line 8 getRandomShape is called before its definition, so a NameError would occur.
What you can do is to put all the code that is not in a function, other than the import statements inside a main() function. And at the end you add:
if __name__ == ‘__main__’:
main()
When the program is called it would execute the main() function, and it would not matter if you put the function before or after others. The only thing that matters is you only call functions after they are already defined.
You can learn more about it here.
There are many more problems with this code, and this only fixes the NameError
that you are currently facing.

Python rock, paper, scissors, problem with else/elif statements

I am trying to make a rock, paper, scissors game, but I think I am doing something wrong with the else/elif statements.
import random
list = ['R', 'P', 'S']
def play():
x = input('Please input R, P, or S: ').upper()
y = random.choice(list)
if x == y:
print('You both picked {}, pick again'.format(x))
play()
elif (x == 'r' and y == 's') or (x == 'p' and y == 'r') or (x == 's' and y == 'p'):
print('You won! You picked {} and computer picked {}'.format(x,y))
else:
print('You lost. You picked {} and computer picked {}'.format(x,y))
play()
You have 'R', 'P', 'S' in list and 'r', 'p', 's' in your test. So == tests in your if will always be evaluated to False.
Another thing: you should avoid calling a variable list. That's a python built-in type.
Last comment (credits to #JoshuaVoskamp), your code does not handle the case where the answer is not in ['R', 'S', 'P'].
So here is a correct solution summing up the different comments made:
import random
choices = ['R', 'P', 'S']
def play():
x = input('Please input R, P, or S: ').upper()
y = random.choice(choices)
if x == y:
print('You both picked {}, pick again'.format(x))
play()
elif x + y in ['RS', 'PR', 'SP']: # clever test proposed by #user17242583
print('You won! You picked {} and computer picked {}'.format(x,y))
elif x in ['R', 'S', 'P']:
print('You lost. You picked {} and computer picked {}'.format(x,y))
else:
print('Wrong input!')
play()
play()
Try This
import tkinter as tk
from PIL import Image,ImageTk
window=tk.Tk()
window.geometry("300x500")
window.title("Rock Paper Scissors")
image=Image.open('rps.jpg')
image.thumbnail((300,300),Image.ANTIALIAS)
photo=ImageTk.PhotoImage(image)
label_image=tk.Label(image=photo)
label_image.grid(column=15,row=0)
#global variables
USER_SCORE=0
COMP_SCORE=0
USER_CHOICE=""
COMP_CHOICE=""
def choice_to_number(choice):
rps={'scissor':0,'paper':1,'rock':2}
return rps[choice]
def number_to_choice(number):
rps={0:'scissor',1:'paper',2:'rock'}
return rps[number]
def random_computer_choice():
return random.choice(['scissor','paper','rock'])
def result(human_choice,comp_choice):
global USER_SCORE
global COMP_SCORE
user=choice_to_number(human_choice)
comp=choice_to_number(comp_choice)
if(user==comp):
print("Tie")
elif((user-comp)%3==1):
print("Sorry !! Computer win")
USER_SCORE+=1
else:
print("Congarts !! You win")
COMP_SCORE+=1
#Text
text_area=tk.Text(master=window,height=12,width=30)
text_area.grid(column=15,row=4)
answer="Your Choice: {uc} \nComputer's Choice : {cc} \n Your Score : {u} \n Computer Score : {c} \n\n made by diwas pandey ".format(uc=USER_CHOICE,cc=COMP_CHOICE,u=USER_SCORE,c=COMP_SCORE, font=('arial',24,'bold'))
text_area.insert(tk.END,answer)
#Event Handling
def rock():
global USER_CHOICE
global COMP_CHOICE
USER_CHOICE='rock'
COMP_CHOICE=random_computer_choice()
result(USER_CHOICE,COMP_CHOICE)
def paper():
global USER_CHOICE
global COMP_CHOICE
USER_CHOICE='paper'
COMP_CHOICE=random_computer_choice()
result(USER_CHOICE,COMP_CHOICE)
def scissor():
global USER_CHOICE
global COMP_CHOICE
USER_CHOICE='scissor'
COMP_CHOICE=random_computer_choice()
result(USER_CHOICE,COMP_CHOICE)
#buttons
button1=tk.Button(text=" Scissor ",bg="red",command=scissor, height=1,width=8,font=('arial',15,'bold'))
button1.grid(column=15,row=1)
button2=tk.Button(text=" Paper ",bg="pink",command=paper, height=1,width=8,font=('arial',15,'bold'))
button2.grid(column=15,row=2)
button3=tk.Button(text=" Rock ",bg="yellow",command=rock, height=1,width=8,font=('arial',15,'bold'))
button3.grid(column=15,row=3)
window.mainloop()```
You use upper() method for the input, therefore the letter in the elif statement should be all uppercase, like:
import random
computer = ['R', 'P', 'S']
def play():
x = input('Please input R, P, or S: ').upper()
y = random.choice(computer)
if x == y:
print('You both picked {}, pick again'.format(x))
play()
elif (x == 'R' and y == 'S') or (x == 'P' and y == 'R') or (x == 'S' and y == 'P'):
print('You won! You picked {} and computer picked {}'.format(x,y))
else:
print('You lost. You picked {} and computer picked {}'.format(x,y))
play()

Rock Paper Scissors Keeping Score

I am trying to create a rock paper scissors game that keeps score but when I run this program the score resets each time. What do I need to change so that I can properly keep score?
import random
def rockPaperScissors():
playerScore = 0
computerScore = 0
print ""
p = raw_input("Type 'r' for rock, 'p' for paper or 's' for scissors: ")
choices = ['r', 'p', 's']
c = random.choice(choices)
print ""
print "Your move:", p
print "Computer's move:", c
print ""
if p == c:
print "Tie"
elif p == 'r' and c == 's':
playerScore += 1
print "You win"
elif p == 'p' and c == 'r':
playerScore += 1
print "You win"
elif p == 's' and c == 'p':
playerScore += 1
print "You win"
elif c == 'r' and p == 's':
computerScore += 1
print "You lose"
elif c == 'p' and p == 'r':
computerScore += 1
print "You lose"
elif c == 's' and p == 'p':
computerScore += 1
print "You lose"
else:
print "Try again"
print ""
print "Your score:", str(playerScore)+ ", Computer score:", str(computerScore)
while True:
rockPaperScissors()
You're calling the function in a loop. The first thing the function does is create a local variable for the score. When the function ends, that score is thrown away. It doesn't persist through multiple calls. You should return the new score and assign the new values to counters:
import random
def rockPaperScissors():
playerScore = 0
computerScore = 0
...
return playerScore, computerScore
player = 0
computer = 0
while True:
p, c = rockPaperScissors()
player += p
computer += c
print "Your score:", str(player)+ ", Computer score:", computer
Each time you run the function, you are resetting the scores. Define computerScore and playerScore outside of the function, then it will keep the values even when running the function multiple times. Use global to "import" the global variable into the function scope.
playerScore = 0
computerScore = 0
def rockPaperScissors ():
global playerScore
global computerScore
OTHER CODE

Undefined Function?

I am not sure why I am getting an error that game is not defined:
#!/usr/bin/python
# global variables
wins = 0
losses = 0
draws = 0
games = 0
# Welcome and get name of human player
print 'Welcome to Rock Paper Scissors!!'
human = raw_input('What is your name?')
print 'Hello ',human
# start game
game()
def game():
humanSelect = raw_input('Enter selection: R - Rock, P - Paper, S - Scissors, Q - Quit: ')
while humanSelect not in ['R', 'P', 'S', 'Q']:
print humanSelect, 'is not a valid selection'
humanSelect = raw_input('Enter a valid option please')
return humanSelect
main()
Because, at the time the statement game() is executed you have not yet reached the statement def game(): and game is, therefore, undefined.
If you move game() to after def game() you will then get a similar error on main() which is harder to fix as you don't appear to be defining a function called main anywhere in the code.
You have to define the function game before you can call it.
def game():
...
game()
Okay, I spent some time tinkering with this today and now have the following:
import random
import string
# global variables
global wins
wins = 0
global losses
losses = 0
global draws
draws = 0
global games
games = 0
# Welcome and get name of human player
print 'Welcome to Rock Paper Scissors!!'
human = raw_input('What is your name? ')
print 'Hello ',human
def readyToPlay():
ready = raw_input('Ready to Play? <Y> or <N> ')
ready = string.upper(ready)
if ready == 'Y':
game()
else:
if games == 0:
print 'Thanks for playing'
exit
else:
gameResults(games, wins, losses, draws)
return
def game():
global games
games += 1
human = humanChoice()
computer = computerChoice()
playResults(human, computer)
readyToPlay()
def humanChoice():
humanSelect = raw_input('Enter selection: R - Rock, P - Paper, S - Scissors: ')
while humanSelect not in ['R', 'P', 'S']:
print humanSelect, 'is not a valid selection'
humanSelect = raw_input('Enter a valid option please')
return humanSelect
def computerChoice():
computerInt = random.randint(1, 3)
if computerInt == '1':
computerSelect = 'R'
elif computerInt == '2':
computerSelect = 'P'
else:
computerSelect = 'S'
return computerSelect
def playResults(human, computer):
global draws
global wins
global losses
if human == computer:
print 'Draw'
draws += 1
elif human == 'R' and computer == 'P':
print 'My Paper wrapped your Rock, you lose.'
losses += 1
elif human == 'R' and computer == 'S':
print 'Your Rock smashed my Scissors, you win!'
wins += 1
elif human == 'P' and computer == 'S':
print 'My Scissors cut your paper, you lose.'
losses += 1
elif human == 'P' and computer == 'R':
print 'Your Paper covers my Rock, you win!'
wins += 1
elif human == 'S' and computer == 'R':
print 'My Rock smashes your Scissors, you lose.'
losses += 1
elif human == 'S' and computer == 'P':
print 'Your Scissors cut my Paper, you win!'
wins += 1
def gameResults(games, wins, losses, draws):
print 'Total games played', games
print 'Wins: ', wins, ' Losses: ',losses, ' Draws: ', draws
exit
readyToPlay()
I am going to work on the forcing the humanSelect variable to upper case in the same manner that I did with ready, ready = string.upper(ready). I ran into indentation errors earlier today, but will iron that out later tonight.
I do have a question. Is it possible to use a variable between the () of a raw_input function similar to this:
if game == 0:
greeting = 'Would you like to play Rock, Paper, Scissors?'
else:
greeting = 'Play again?'
ready = raw_input(greeting)

Categories