Reputation: 3
Edit: Thank you for all the help!
So I'm in a beginner class, don't have much experience and I've ran into this problem: I'm trying to make the game repeat five times and what I want to happen is
Player inputs choice
Game spits out result
Move onto round 2
Ask for choice again
Game spits out result... etc
What actually ends up happening though is
Player inputs choice
Game spits out result
Move onto round 2
Program asks for choice (I think)
The if/elif is completely disregarded after round 1 as in whatever I input spits no result
Can hit enter five times before program ends
My challenge here is doing this while trying to be as concise as possible because I can do it but the resulting program would be really long and really ugly.
Anyway, to ask a specific question, is it even possible to reuse the same variable five times like this? And why is the if/else completely ignored after round 1?
import random
cpu_choice = ["rock","paper","scissors","dynamite"]
for i in range(5):
choice = input().lower().strip("!.?")
cpu_choice = random.choice(cpu_choice)
if "rock" in choice:
if cpu_choice == "rock":
print("It's a tie!")
elif cpu_choice == "scissors":
print("Dang, I lost!")
elif cpu_choice == "paper" or cpu_choice == "dynamite":
print("Haha! I won!")
elif "paper" in choice:
if cpu_choice == "rock":
print("Dang, I lost!")
elif cpu_choice == "paper":
print("It's a tie!")
elif cpu_choice == "scissors" or cpu_choice == "dynamite":
print("Haha! I won!")
elif "scissors" in choice:
if cpu_choice == "rock":
print("Haha! I won!")
elif cpu_choice == "scissors":
print("It's a tie!")
elif cpu_choice == "paper" or cpu_choice == "dynamite":
print("Dang, I lost!")
elif "dynamite" in choice:
if cpu_choice == "scissors":
print("Dang, I lost!")
elif cpu_choice == "dynamite":
print("It's a tie!")
elif cpu_choice == "paper" or cpu_choice == "rock":
print("Haha! I won!")
else:
print("Please use rock, paper, scissors, or dynamite!")
```
Upvotes: 0
Views: 1436
Reputation: 23119
I initially posted an answer. A few minutes later, there were 4 answers, all saying the same thing. I thought about deleting my answer or just leaving it, but I figured it would be better to offer something more to the asker and the community by providing an enhanced answer.
As the other answers point out, your problem is that you are using the cpu_choice
variable for two purposes, and that breaks the logic of your program. You can get more details from the other answers.
One thing you'll learn as you become a better programmer is to recognize when you've got repetition that can be eliminated. We call this the DRY, or "Don't Repeat Yourself" principle. This is an obvious characteristic of your code...there are four blocks of code that are nearly identical, with the only difference being the particular values of some string constants.
In a case like this, you'll learn that you want to parameterize the duplicated code so that you only need one copy of that code. This doesn't only save you time and space on your screen, but it also leads to code that is easier to maintain. If you want to change the logic for how you deal with comparing the values that the user typed in with the computer's choice, you have to make the change in four places. If you had reduced your code down to a single block, you would only then have to make one change.
Here's a version of your code that acts on the DRY principle to reduce the four code blocks down to one. It has a few other enhancements as well. It prompts the user so that they know what to enter. It will play as many rounds as the user wants, and user can quit the game by pressing Return without entering any letters:
import random
# Valid choices, each with a list of what that choice can beat
choices = {"rock":["scissors"],"paper":["rock"],"scissors":["paper" "dynamite"],"dynamite":["scissors"]}
while True:
print("rock, paper, scissors or dynamite? >", end="")
user_choice = input().lower().strip("!.?")
cpu_choice = random.choice(list(choices.keys()))
if not user_choice:
# End the program on an empty input
break
elif user_choice not in choices:
# Complain about an invalid choice
print("That's not a valid input value!")
else:
# Show what the computer picked
print("I picked " + cpu_choice)
# Do the appropriate thing based on the two choices
if user_choice == cpu_choice:
# The two choices were the same
print("It's a tie!")
elif cpu_choice in choices[user_choice]:
# The computer's choice is not in the list of things that the user's choice beats
print("Haha! I won!")
else:
# The computer's choice is in the list of things that the user's choice beats
# beats, so it must have won
print("Dang, I lost!")
Here's what a sample run looks like:
rock, paper, scissors or dynamite? >rock
I picked paper
Dang, I lost!
rock, paper, scissors or dynamite? >rock
I picked scissors
Haha! I won!
rock, paper, scissors or dynamite? >paper
I picked paper
It's a tie!
rock, paper, scissors or dynamite? >blah
That's not a valid input value!
rock, paper, scissors or dynamite? >rock
I picked dynamite
Dang, I lost!
rock, paper, scissors or dynamite? >
I hope this helps you by teaching you about the DRY principle!
Upvotes: 1
Reputation: 5479
You are right. Writing a whole bunch of if/elif statements makes for very ugly code. There is a much more efficient way of designing this game by taking advantage of the circular hierarchy of the moves. If you assign a value to each move as in {'r':0, 'p':1, 'd':2, 's': 3}, you realize that player1 wins if and only if the difference between player1 and player2's score is 1 or 2 or -3. You can use this fact to markedly simplify the code. The following code runs 5 times:
import random
player_dic = {'r':0, 'p':1, 'd':2, 's': 3}
for i in range(5):
player_letter = input('Enter r or p or d or s: ')
player_number = player_dic[player_letter]
computer_choice = random.choice(list(player_dic.items()))
difference = (computer_choice[1] - player_number)
print(f'Player: {player_letter}, Computer: {computer_choice[0]}')
if difference == 0:
print("It's a tie!")
elif difference in [1,2,-3]:
print('Computer wins!')
else:
print('Player wins')
Upvotes: 0
Reputation: 2731
This two lines of code is contradict:
cpu_choice = ["rock","paper","scissors","dynamite"]
cpu_choice = random.choice(cpu_choice)
When it is the first run, it uses the list, and assign it as a choice from it, take "rock" for example. But the second time, it uses "rock" as choices, not the list you declared earlier. Just change the variable a bit and you are good to go:
Full working code:
import random
choices = ["rock","paper","scissors","dynamite"]
for i in range(5):
choice = input("Your input: ").lower().strip("!.?")
cpu_choice = random.choice(choices)
if "rock" in choice:
if cpu_choice == "rock":
print("It's a tie!")
elif cpu_choice == "scissors":
print("Dang, I lost!")
elif cpu_choice == "paper" or cpu_choice == "dynamite":
print("Haha! I won!")
elif "paper" in choice:
if cpu_choice == "rock":
print("Dang, I lost!")
elif cpu_choice == "paper":
print("It's a tie!")
elif cpu_choice == "scissors" or cpu_choice == "dynamite":
print("Haha! I won!")
elif "scissors" in choice:
if cpu_choice == "rock":
print("Haha! I won!")
elif cpu_choice == "scissors":
print("It's a tie!")
elif cpu_choice == "paper" or cpu_choice == "dynamite":
print("Dang, I lost!")
elif "dynamite" in choice:
if cpu_choice == "scissors":
print("Dang, I lost!")
elif cpu_choice == "dynamite":
print("It's a tie!")
elif cpu_choice == "paper" or cpu_choice == "rock":
print("Haha! I won!")
else:
print("Please use rock, paper, scissors, or dynamite!")
Upvotes: 0
Reputation: 4875
Replace cpu_choice to cpu_ch
import random
cpu_ch = ["rock","paper","scissors","dynamite"]
for i in range(5):
choice = input().lower().strip("!.?")
cpu_choice = random.choice(cpu_ch)
if choice == "rock":
if cpu_choice == "rock":
print("It's a tie!")
elif cpu_choice == "scissors":
print("Dang, I lost!")
elif cpu_choice == "paper" or cpu_choice == "dynamite":
print("Haha! I won!")
elif choice == "paper":
if cpu_choice == "rock":
print("Dang, I lost!")
elif cpu_choice == "paper":
print("It's a tie!")
elif cpu_choice == "scissors" or cpu_choice == "dynamite":
print("Haha! I won!")
elif choice == '"scissors':
if cpu_choice == "rock":
print("Haha! I won!")
elif cpu_choice == "scissors":
print("It's a tie!")
elif cpu_choice == "paper" or cpu_choice == "dynamite":
print("Dang, I lost!")
elif choice == "dynamite":
if cpu_choice == "scissors":
print("Dang, I lost!")
elif cpu_choice == "dynamite":
print("It's a tie!")
elif cpu_choice == "paper" or cpu_choice == "rock":
print("Haha! I won!")
else:
print("Please use rock, paper, scissors, or dynamite!")
Upvotes: 0
Reputation: 617
You're using cpu_choice for two different things. The first time, its a list of potential choices that the cpu has. But then you redefine it to be the outcome that the cpu has actually chosen. This means (say the cpu picked rock in the first iteration) that in the second one you have '''cpu_choice = random.choice("rock")''', and because python treats strings as lists, it will output "r" "o" "c" or "k". You don't get an error message for that, because you have no else statement in your inner if statements.
Just rename your second line to potential_choices and it will be fine.
Upvotes: 0
Reputation: 154
The problem with your code is this line: cpu_choice = random.choice(cpu_choice)
.you choose an object from the list , then you save it in the cpu_choice itself.
In other words after the first round you dont have access to the cpu_choice itself,because you overwrited it last round. the trick is simple; change variable name:
import random
cpu_choice2 = ["rock","paper","scissors","dynamite"]
for i in range(5):
choice = input().lower().strip("!.?")
cpu_choice = random.choice(cpu_choice2)
if "rock" in choice:
if cpu_choice == "rock":
print("It's a tie!")
elif cpu_choice == "scissors":
print("Dang, I lost!")
elif cpu_choice == "paper" or cpu_choice == "dynamite":
print("Haha! I won!")
I just added a 2
to your cpu_list name.
Upvotes: 0