These are the instructions: This program should be written using a menu driven interface. It should contain at least 6 functions, as follows (you can have more if you think you need others). You should choose descriptive function names to properly describe their function (follow the convention for properly naming functions). Just to be clear, you should NOT have functions called function1, function2, etc. Replace the names below with your own function names in your code.
When I run it, I get an error code saying "expected an indented block" for the line if comp(==1 and user ==3).
Please let me know what's wrong, thanks!
#import random module
import random
#main function
def main():
#program message
print("Rock, Paper, Scissors Game")
#initializing variables that would hold choices of user and computer
comp = 1
user = 1
while comp == user:
print("Enter your choice in range from 1 to 3")
#prompt user to enter choice
user = int(input("Your choice: "))
#randomly assign choice to computer
comp = random.randint(1,3)
#display choice of computer
print("Computer Choice : ",comp)
#display game drawn message, when same choices
if (comp == user):
print("Game Drawn. Select again")
#calling function to decide winner
winner (comp, user)
#winner function
def winner(comp, user):
#rock and scissor choice
if(comp == 1 and user ==3):
print("Computer win")
print("The rock smashes scissor")
elif(comp == 3 and user ==1):
print("User win")
print("The rock smashes scissor")
else:
#paper and rock choice
if(comp == 1 and user == 2):
print("User win")
print("The paper wraps rock")
elif (comp == 2 and user ==1):
print("Computer win")
print("Scissors cut paper")
elif (comp == 2 and user == 3):
print("User win")
print("Scissors cut paper")
else:
print("Invalid selection")
#calling main function
main()
Besides the answer from Nathaniel Ford, your if-elif-else indendation is wrong at some places as well.
if (condition):
print "hi"
elif (condition):
print "hi again"
else:
print "hi again vol3"
This is the correct way to indendent if-elif-else conditions.
The problem is with the previous code line:
def winner(comp, user):
def is defining a function, and expects that function to have a body. Because you back the indentation out to the top level, the def body has nothing (not even a pass), and thus won't compile.
But note that isn't your only indentation problem. The definition of main prints one line print("Rock, Paper, Scissors Game"), and then sets some variables and... quits. Because the indentation of while comp == user: backs out a level, it doesn't exist inside the main definition. This a problem with pretty much every new block of your code. You should read up how Python structures code with indentation.
Related
:D I've make a little rock paper scissors game in Python just for fun and practice and I've been trying to implement a little scoring system that doesn't seem to want to work properly and I'm not sure how to solve the problem.
import random
import messages
def gameOn():
choice = ["rock", "paper", "scissors"]
computer_choice = random.choice(choice)
player_choice = input("Please chose Rock/Paper/Scissors: ")
player_choice = player_choice.lower()
total_score = 0
while True:
#Makes sure the user enters a valid option.
if player_choice not in("rock", "paper", "scissors"):
print("Choice is not correct!")
#Prints in case both the computer and the player chose the same option.
elif computer_choice == player_choice:
print("You chose the same.")
#Computer choses ROCK.
elif computer_choice == "rock" and player_choice == "paper":
print(messages.win[0])
total_score += 1
print(total_score)
elif computer_choice == "rock" and player_choice == "scissors":
print(messages.lose[0])
#Computer choses PAPER.
elif computer_choice == "paper" and player_choice == "rock":
print(messages.lose[1])
elif computer_choice == "paper" and player_choice == "scissors":
print(messages.win[1])
total_score += 1
print(total_score)
#Computer choses SCISSORS.
elif computer_choice == "scissors" and player_choice == "rock":
print(messages.win[2])
total_score += 1
print(total_score)
elif computer_choice == "scissors" and player_choice == "paper":
print(messages.lose[2])
#Asks the user if he/she wants to play again and restarts the loop if so.
answer = input("Would you like to play again or see your score? Yes/No/Score ")
if answer in ("yes", "Yes", "y", "Y", "yup"):
print("Game starting again!")
gameOn()
elif answer in ("Score", "score"):
print("Your total score is " + str(total_score))
answer = input("Would you like to play again or see your score? Yes/No/Score ")
print("Game starting again!")
gameOn()
else:
print("Goodbye!")
break
gameOn()
The incrementation in itself works but what I want to do is, if the player wins multiple round and at the end writes "score" he should be able to see all the points he has earned. At the moment the score variable get reset every time a new game starts so the score of the use is always either 0 or 1 if he won the round. How could I prevent this behavior?
Thank you very much :D and I hope it's not a too stupid question.
I would not advise using recursion for this. You also shouldn't need to use global variables.
I would rather just loop with while True in your gameOn function and break if the player wants to exit, so that your score is kept in scope.
Also your "Choice is not correct!" was not working because of the indentation.
import random
import messages
def gameOn():
choice = ["rock", "paper", "scissors"]
total_score = 0
while True:
computer_choice = random.choice(choice)
player_choice = input("Please chose Rock/Paper/Scissors: ")
player_choice = player_choice.lower()
while True:
#Makes sure the user enters a valid option.
if player_choice in("rock", "paper", "scissors"):
break
print("Choice is not correct!")
#Prints in case both the computer and the player chose the same option.
elif computer_choice == player_choice:
print("You chose the same.")
#Computer choses ROCK.
elif<computer_choice == "rock" and player_choice == "paper":
print(messages.win[0])
total_score += 1
print(total_score)
elif computer_choice == "rock" and player_choice == "scissors":
print(messages.lose[0])
#Computer choses PAPER.
elif computer_choice == "paper" and player_choice == "rock":
print(messages.lose[1])
elif computer_choice == "paper" and player_choice == "scissors":
print(messages.win[1])
total_score += 1
print(total_score)
#Computer choses SCISSORS.
elif computer_choice == "scissors" and player_choice == "rock":
print(messages.win[2])
total_score += 1
print(total_score)
elif computer_choice == "scissors" and player_choice == "paper":
print(messages.lose[2])
#Asks the user if he/she wants to play again and restarts the loop if so.
answer = input("Would you like to play again or see your score? Yes/No/Score ")
if answer in ("Score", "score"):
print("Your total score is " + str(total_score))
answer = input("Would you like to play again or see your score? Yes/No/Score ")
print("Game starting again!")
elif answer in ("yes", "Yes", "y", "Y", "yup"):
print("Game starting again!")
else:
print("Goodbye!")
break #this makes your game stop
gameOn()
I would suggest defining a parameter to your gameOn function, so it looks like this:
def gameOn(total_score=0):
# REMOVE this following line:
total_score = 0
# because we already defined it on parameter
# when user wins, and you call the function again,
# give current total_score to it
gameOn(total_score)
since in each function call you are giving the current score, now your app should be able to keep track of actual total score
There are 2 different ways to answer this, depending on the meaning of «every time a new game starts».
Do you want to persist the score if you call the gameOn function multiple times?
Or do you want to persist the score also if you run the program again?
Persisting the score between gameOn calls
The problem is the scope of your total_score variable, which is local. Hence it’s cleaned after each gameOn execution. The simplest way to work around this is to set it as global:
import random
import messages
# Total score is initialized outside of any game
total_score = 0
def gameOn():
choice = ["rock", "paper", "scissors"]
computer_choice = random.choice(choice)
player_choice = input("Please chose Rock/Paper/Scissors: ")
player_choice = player_choice.lower()
global total_score
# Then the rest of your existing function
# ...
Advice: With time, you’ll get better in Python, and you’ll realize such global variable is usually considered bad, because of the lack of isolation it has. For larger projects, relying on globally defined stuff makes the code more difficult to evolve, increases the cognitive load of the developer, makes it harder to test... but for such a small script it’s just perfectly fine.
My point is: it’s handy, but please keep in mind there are other ways to do it. They are more complex, and over-engineered in this case, but the key take away shouldn’t be thought as "I need to use global variable as soon as I want to persist a state" ;)
Persisting the score between runs.
If your goal is to keep the score between every time you run the script, then you need to save it "outside" of the current Python session memory.
A very simple way to do this is to save it to a file. Python’s built-in pickle library is made for that (there are many other options, depending on if you want this to be usable by other programs or not, or by humans. When it’s just for Python, pickle is super simple and fast and reliable)
In this case, what you would need is to:
load the existing score when the game starts, if an existing score exists
save it at the end of the game
import random
import messages
import pickle
import os
def gameOn():
choice = ["rock", "paper", "scissors"]
computer_choice = random.choice(choice)
player_choice = input("Please chose Rock/Paper/Scissors: ")
player_choice = player_choice.lower()
score_file = "score.dat"
# Check if an existing score existed
if os.path.isfile(score_file):
with open(score_file, "rb") as f:
total_score = pickle.load(f)
else:
total_score = 0
# Then the rest of your existing function
# ...
# and at the end of the function, we save the score to the file
with open(score_file, "wb") as f:
pickle.dump(total_score, f)
This should give you pointers to what you exactly want to achieve.
This question already has answers here:
Is 'input' a keyword in Python?
(2 answers)
Call built-in function if overwritten by a variable of the same name
(3 answers)
Using function names as variables in python
(2 answers)
Closed 2 years ago.
I have tried to add a 'while True' loop but it shows the error 'str object is not callable'. Please help me on this one. I need an extension of this already written code game.
import random
user_score = 0
computer_score = 0
user_score = 0
computer_score = 0
input = input("Choose your move, Rock, Paper or Scissors: ").upper()
comp = ["ROCK", "PAPER", "SCISSORS"]
computer_move = random.choice(comp)
if input == "ROCK":
if computer_move == "PAPER":
print("You lost. Better luck next time!")
computer_score += 1
elif computer_move == "SCISSORS":
print("You won! Well done.")
user_score += 1
elif input == "PAPER":
if computer_move == "ROCK":
print("You won! Well done.")
user_score += 1
elif computer_move == "SCISSORS":
print("You lost. Better luck next time!")
computer_score += 1
elif input == "SCISSORS":
if computer_move == "ROCK":
print("You lost. Better luck next time!")
computer_score += 1
elif computer_move == "PAPER":
print("You won! Well done.")
user_score += 1
elif input == computer_move:
print("It's a tie!")
print(f"Your Score: {user_score} ; Computer Score: {computer_score} ")
This is happening because you are defining your input variable as this:
input = input("Choose your move, Rock, Paper or Scissors: ").upper()
input is a built-in function in python, don't use variables with keywords/built-in functions as names.
In your second iteration inside the while, when you try to take input with the input() function, it gives an error since you overshadowed it with your string input (Python is dynamically-typed) so it's no longer the function <built-in function input> which could help you take the input in current scope. You can define it like this:
choice = input("Choose your move, Rock, Paper or Scissors: ").upper()
You can try something like this:
while(True):
# your code
answer = input("Do you want to play again? (y / n): ")
if (answer == "n") break
With this code, the player will be asked to input either "y" or "n". If the answer is anything different than "n", the game will re-start. Otherwise it will not (the program will break out of the loop).
the problem you encountered resulted from naming the variable holding the user input input thus when using the function input the secon time it instead tried calling the variable holding the string of the previous use of input.
change the name of the variable input to something different like user_input and then looping should work.
I am creating a rock, paper, scissors game. I want it to be best of 3 matches and to be able to verify user input. I keep running into issues with the user input. I have tried multiple variations but I can't seem to figure it out. I know my code is probably messy, so any input on how to clean it up would be greatly appreciated. Thank you so much for your time.
import random
import sys
import time
print("Hello and welcome to the Rock, Paper, Scissors tournament.\n"
"The tournament will be the best of 3 wins.\n"
"It will be you against our highly intelligent computer opponent.\n"
"Good luck!")
# Create a function for the game
def play_game():
user_count = 0
comp_count = 0
tie_game = 0
while comp_count < 2 and user_count < 2:
user_choice = (int(input("-------------------------------------------"
"\nEnter choice by typing 1 2 or 3: \n 1. Rock \n 2. paper \n 3. scissor \n"
"-------------------------------------------\n")))
if user_choice == 1:
user_choice_name = 'Rock'
elif user_choice == 2:
user_choice_name = 'Paper'
elif user_choice == 3:
user_choice_name = 'Scissor'
else:
print("Please pick a valid number")
print(f"\nYou have chosen: {user_choice_name}")
print("\nNow it's the computer's turn to pick......")
time.sleep(3)
comp_choice = random.randint(1, 3)
if comp_choice == 1:
comp_choice_name = 'Rock'
elif comp_choice == 2:
comp_choice_name = 'Paper'
else:
comp_choice_name = 'Scissor'
print(f"\nComputer has chosen: {comp_choice_name}\n")
if user_choice == 1 and comp_choice == 2:
comp_count += 1
print("Computer wins this round with Paper! "
f"\n Computer: {comp_count}"
f"\n You: {user_count} \n\n")
elif user_choice == 1 and comp_choice == 3:
user_count += 1
print("You win this round with Rock!"
f"\n Computer: {comp_count}"
f"\n You: {user_count} \n\n")
elif user_choice == 2 and comp_choice == 1:
user_count += 1
print("You win this round with Paper!"
f"\n Computer: {comp_count}"
f"\n You: {user_count} \n\n")
elif user_choice == 2 and comp_choice == 3:
comp_count += 1
print("Computer wins this round with Scissor!"
f"\n Computer: {comp_count}"
f"\n You: {user_count} \n\n")
elif user_choice == 3 and comp_choice == 2:
user_count += 1
print("You win this round with Scissor!"
f"\n Computer: {comp_count}"
f"\n You: {user_count} \n\n")
elif user_choice == 3 and comp_choice == 1:
user_count += 1
print("Computer wins this round with Rock!"
f"\n Computer: {comp_count}"
f"\n You: {user_count} \n\n")
else:
if user_choice == comp_choice:
tie_game += 1
print(f"This round was a tie! Both choosing {user_choice_name}, try again!"
f"\n Computer: {comp_count}"
f"\n You: {user_count} \n\n")
else:
print(f'The game is now over with a score of: \n You:{user_count} \n to \n Computer:{comp_count}')
again = str(input("Do you want to play again, type 'yes' or 'no' \n"))
if again.lower() == "no":
print('Thank you for playing!')
sys.exit()
else:
play_game()
play_game()
Since I had a few minutes to kill with a cup of coffee, here's a rewrite of your program with a bunch of improvements, the validation you asked about and some tips on coding style:
import random
import time
print("Hello and welcome to the Rock, Paper, Scissors tournament.\n"
"The tournament will be the best of 3 wins.\n"
"It will be you against our highly intelligent computer opponent.\n"
"Good luck!")
# to avoid repeating these values over and over and changing numbers in to string,
# just defining them here. Name in capitals because it's global (generally bad)
# an even nicer solution would be to write a Game() class and put everything in
# there, but it would be a bit more advanced
RSP_OPTIONS = {
1: 'Rock',
2: 'Scissor',
3: 'Paper'
}
def get_user_choice():
# keep asking until a valid value is returned
while True:
# this is a bit fancy, but let's say you want to reuse the game for similar games
# with different options from rock, scissor, paper, you'd want this code to still work
# get a list of string versions of the numbers
numbers = list(map(str, RSP_OPTIONS.keys()))
# join them together like you presented them: 1, 2 or 3
options = ', '.join(numbers[:-1]) + ' or ' + numbers[-1] + ':\n'
# add the descriptions
options = options + ''.join(f'{n}: {name}\n' for n, name in RSP_OPTIONS.items())
try:
user_choice = (int(input("-------------------------------------------\n"
f"Enter choice by typing {options}"
"-------------------------------------------\n")))
except ValueError:
# any invalid option
user_choice = -1
# check if it's one of the valid options
if user_choice in RSP_OPTIONS:
return user_choice
else:
# it makes sense to generate a new line where you want it, instead of having
# to put new line characters at the start of other strings
print("Please pick a valid number\n")
def beats(choice1, choice2):
# choice1 beats choice2 if it's one greater, except when choice2 == 3 and choice1 == 1
# but to make it even nicer and have it work for other similar games, you could say
# "except when choice1 == the max choice and choice2 == the min choice"
return (choice2 - choice1 == 1 or
(choice1 == max(RSP_OPTIONS.keys()) and choice2 == min(RSP_OPTIONS.keys())))
# Create a function for the game
def play_game():
user_count = 0
comp_count = 0
tie_game = 0
# this is what you really want, best out of three, ties not counted?
while comp_count + user_count < 3:
user_choice = get_user_choice()
print(f"You have chosen: {RSP_OPTIONS[user_choice]}\n")
print("Now it's the computer's turn to pick......\n")
# this wait is not very nice, the user might try to hit enter or something
# you could consider printing the countdown, or telling the user to please wait
# even then, it's kind of silly to pretend the computer has to work hard here
time.sleep(3)
# this choice is always valid, so no problem
comp_choice = random.randint(1, 3)
# note that you don't need the name, you can just look it up whenever in RSP_OPTIONS
print(f"\nComputer has chosen: {RSP_OPTIONS[comp_choice]}\n")
# getting rid of some repetition, note how the code really reads like what is intended
if beats(comp_choice, user_choice):
comp_count += 1
# nice to also say what really beat them
print(f"Computer wins this round with {RSP_OPTIONS[comp_choice]} over {RSP_OPTIONS[user_choice]}!\n")
elif beats(user_choice, comp_choice):
user_count += 1
print(f"You win this round with {RSP_OPTIONS[user_choice]} over {RSP_OPTIONS[comp_choice]}!\n")
else:
# you can only get here on a tie
tie_game += 1
print(f"This round was a tie! Both choosing {RSP_OPTIONS[user_choice]}, try again!\n")
# you always print this, so just do it after the options:
print(f"Computer: {comp_count}\n"
f"You: {user_count}\n\n")
else:
print(f'The game is now over with a score of:\n You:{user_count}\n to\n Computer:{comp_count}\n')
again = str(input("Do you want to play again, type 'yes' or 'no' \n"))
# let's quit on anything starting with n
if again.lower()[0] == "n":
print('Thank you for playing!\n')
# instead of exiting hard, maybe just return, telling the caller we don't want to play again
return False
else:
# you were calling play_game again, but that causes the game to get more and more calls
# on top of each other, ultimately reaching an error state
# by returning first and then calling again, you avoid that problem
return True
# the function returns whether it should play again
while play_game():
pass
# once it leaves the loop, the game stops automatically here, no more code
There's still a lot of room for improvement though; try implementing some more advanced forms of RSP, or make the computer more intelligent than just playing random, but have it use some kind of strategy, perhaps with a bit of randomness mixed in.
And code-wise, try separating the game from the way it is presented on the screen; what if you decided to do this on the web instead of on a console, or in a graphics window? You could also consider putting all the code in a nice class, getting rid of global variables and allowing you to create more copies of the game as needed.
whenever I run this it will work like 25 to 50% of the time and I can't find out why. Previously I had trouble with if statements but that was an easy fix I forgot about but this just baffles me since it actually works... some of the time. By the way this code was made and run on repl.it.
edit: I added a part at the end that prints the variable rng and it says
typeError:'str' pbject is not callable
import random
rng=(random.randint(1,3))
player=input("rock, paper, or scissors ")
if player=="rock":
if rng==1:
print("paper covers your rock")
elif rng==2:
print=("both rock, tie")
elif rng==3:
print("your rock crushes scissors")
else:
print("error")
elif player=="paper":
if rng==1:
print("both paper, tie")
elif rng==2:
print=("your paper covers rock")
elif rng==3:
print("scisors cut your paper")
else:
print("error")
elif player=="scissors":
if rng==1:
print("your scissors cut paper")
elif rng==2:
print=("rock crushes your scissors")
elif rng==3:
print("both scissors, tie")
else:
print("error")
else:
print("error")
On this line:
print=("rock crushes your scissors")
The = is overriding the value of print, turning it into a string instead of a function. This causes your print statement not to print!
So, just remove the = sign. This typo is actually present in your code three times, as pointed out by #chitown88.
I'm working on a code with python, where we've been asked to create a game of Rock, Paper, Scissors using an external file of options (rock, paper, scissors) as opposed to having the code use any user input. However, for some reason, my code doesn't work. When someone inputs "yes", it prints "Let us play now," but that's it. Nothing else happens.
Why isn't the game completing when a user provides "yes" as input?
from random import randrange
def sample():
computer_input = randrange(1,3)
return computer_input
def main():
a = []
infile = open("input2.txt", "r")
for line in infile:
a.append(line)
computer_input = sample()
tied = 0 #games tied
user_won = 0 #games won by user
comp_won = 0 #games won by computer
user_input = ""
computer_input = ""
print("Rules of the game...")
print("Would you like to turn up with a game of rock, paper, or scissors? ;) Yes or no? -->")
answer = input()
if (answer == "yes"):
play = True
print("Let us now play.")
## elif(answer == "no" or "No"):
## play = False
## print("Sorry. Maybe we can play next time ;)")
## else:
## play = False
## print("Please try again!")
## main()
while True:
if(computer_input == "1"):
if(user_input == a[0]):
tied = tied + 1
print("Game is tied!")
elif(user_input == a[1]):
user_won = user_won + 1
print("You won! Paper covers Rock")
elif(user_input == a[2]):
comp_won = comp_won + 1
print("You lost! Rocks knocks out scissors")
## else:
## print("Try again!")
elif (computer_input == "2"):
if (user_input == a[0]):
comp_won = comp_won + 1
print("You lost! Paper covers Rock")
elif(user_input == a[1]):
tied = tied + 1
print("Game is tied!")
elif(user_input == a[2]):
user_won = user_won + 1
print("You won! Scissors cuts Paper")
## else:
## print("Try again!")
else :
if(user_input == a[0]):
user_won = user_won + 1
print("You won! Rock knocks out scissors")
elif(user_input == a[1]):
comp_won = comp_won + 1
print("You lost! Scissors cuts Paper")
elif(user_input == a[2]):
tied = tied + 1
print("Game is tied!")
## else:
## print("Try again!")
##
##print("Game over")
##print("Statistics")
##print("Games tied -->", tied)
##print("Game won by comp -->", comp_won)
##print("Game won by user -->", user_won)
##
main()
Notice that on line 5 below, you set computer_input to the result of sample():
def main():
a = []
infile = open("input2.txt", "r")
for line in infile:
a.append(line)
computer_input = sample()
But then a few lines later, you set it to "":
user_input = ""
computer_input = ""
Your while loop is checking against the value of computer_input, but it assumes it will be a number. It has no case to handle the empty string. I would recommend removing that line.
Also note that your while loop is checking the value of user_input, but you never seem to actually read input into that variable.
There are many, many problems with this code.
Every time you define or use a variable, you should have a clear idea of
why it is defined this way or exactly what this use of the variable is
going to accomplish.
You have a loop, which seems to indicate that you meant for more than
one round of the game to be played when you run the code once.
But there is only one place where the computer's choice is set
to a number 1, 2, or 3, and it occurs only once.
(Besides, as has already been pointed out, then you change the
computer's choice to "" without even reading the number once.)
You have no apparent way to get out of the loop within the logic of the code.
It is unclear what you think you are supposed to be reading from the
user's input file. You put the contents of the file in the array a line
by line, but then you only ever look at a[0], a[1], and a[2].
What were the first three lines of the file supposed to contain?
Why only three lines? What does it mean to ask whether
user_input == a[0]?
(I have a hunch that you were supposed to set the user input on each
round to a member of a, not compare user_input to a member of a.)
(Also notice that you set user_input = "" earlier, so unless you read
empty strings into the entries of a, expressions like
user_input == a[0] will always be false.)
What is the point of setting play = True? (Or even setting
play = False as in the commented-out code?) You never do anything that
would read the value of play.
What is the point of keeping count in the variables tied,
user_won, and computer_won? You never read those variables either,
except when you're setting new values of them.
It might help if you write some smaller functions with very clear
purpose, input and output. The sample() function is promising, but
everything else is in main().
For example, figuring out who won, given the computer's choice and
the player's choice, could be a function.
By writing such a function you would remove dozens of lines of code from
the loop in main(), replacing them with perhaps one line of code.
It's much, much easier to write well-designed loops when
the block of code inside the loop is short.