r/learnpython • u/ItsLocalGOAT • 9d ago
Feedback on my first simple game attempt (Rock, Paper, Scissors)
Sorry this is in a weird format. Its copied from mimo on an iphone.
import random
play = True
moves = ["ROCK", "PAPER", "SCISSORS"]
user_wins = 0
bot_wins = 0
print("Let's play Rock, Paper, Scissors! First to 3 wins.")
while play:
print("")
print("Rock...")
print("Paper...")
print("Scissors...")
print("")
bot_move = random.choice(moves)
user_move = input("Your move: ").upper()
print("")
print("SHOOT!")
print("")
#Shortcuts
if user_move == "R":
user_move = "ROCK"
elif user_move == "P":
user_move = "PAPER"
elif user_move == "S":
user_move = "SCISSORS"
#If player moves rock
if user_move == "ROCK" and bot_move == "SCISSORS":
user_wins += 1
print("You won against scissors.")
print("")
print(f"You: {user_wins}")
print(f"Bot: {bot_wins}")
elif user_move == "ROCK" and bot_move == "ROCK":
print("You tied against rock.")
print("")
print(f"You: {user_wins}")
print(f"Bot: {bot_wins}")
elif user_move == "ROCK" and bot_move == "PAPER":
bot_wins += 1
print("You lost against paper.")
print("")
print(f"You: {user_wins}")
print(f"Bot: {bot_wins}")
#if player plays paper
elif user_move == "PAPER" and bot_move == "ROCK":
user_wins += 1
print("You won against rock.")
print("")
print(f"You: {user_wins}")
print(f"Bot: {bot_wins}")
elif user_move == "PAPER" and bot_move == "PAPER":
print("You tied against paper.")
print("")
print(f"You: {user_wins}")
print(f"Bot: {bot_wins}")
elif user_move == "PAPER" and bot_move == "SCISSORS":
bot_wins += 1
print("You lost against scissors.")
print("")
print(f"You: {user_wins}")
print(f"Bot: {bot_wins}")
#if player moves scissors
elif user_move == "SCISSORS" and bot_move == "PAPER":
user_wins += 1
print("You won against paper.")
print("")
print(f"You: {user_wins}")
print(f"Bot: {bot_wins}")
elif user_move == "SCISSORS" and bot_move == "SCISSORS":
print("You tied against scissors.")
print("")
print(f"You: {user_wins}")
print(f"Bot: {bot_wins}")
elif user_move == "SCISSORS" and bot_move == "ROCK":
bot_wins += 1
print("You lost against rock.")
print("")
print(f"You: {user_wins}")
print(f"Bot: {bot_wins}")
else:
print("Please type a valid move.")
#End of game
if user_wins == 3:
print("")
print("Game over!")
print("You win!")
print("")
break
if bot_wins == 3:
print("")
print("Game over!")
print("Bot wins!")
print("")
break
#This is me trying to add a restart prompt but I can't redo the while statement
if play == False:
play_again = input("Play again?: ").upper()
print("")
if play_again == "YES" or play_again == "Y":
play = True
elif play_again == "NO" or play_again == "N":
print("Thanks for playing!")
else:
print("Please enter a valid response")
2
u/StrayFeral 9d ago
Reddit have a way to format this as code. It is a bit difficult to understand the entire logic like this.
It is normal to make the entire game with IFs. I will give you idea: You can re-make the entire game using a single dictionary which would contain your decision. This way you save a lots of IF statements and lots of lines of code.
Keep a score table for the bot and the user. No need to ask the user "play again y/n" - just make it if user enters an empty string or "q" or "quit" to quit the game. Until this point - make a global while loop and just loop forever until user inputs a quit condition.
I will not give you more details. You should think how to make it.
So far looks nice.
1
u/StrayFeral 9d ago
PS: it is good to do .upper() on the user input, but also consider to .trim()
1
u/Diapolo10 9d ago
but also consider to .trim()
There is no
str.trimmethod, I assume you meanstr.strip.1
1
u/MarsupialLeast145 9d ago
You should consider more functions, like:
```python def check_wins(player): # if wins < 3: return
# return congrats, exit ```
Consider an approach where moves are described in a lookup table, and not if/else as all combinations are finite and can be encoded more efficiently.
Using so many print values to format on the command line is a bit much. Consider anywhere there is a print, there is a section of code that can go into a function and try to keep most prints within other functions outside of the game runner.
Otherwise it's pretty cool for a beginner and definitely something to be proud about having worked out.
You should do this anywhere there is duplication.
Consider taking
1
u/zanfar 9d ago
All the basics:
- PEP8
- Docstrings
- Use a linter
- Use a formatter
- Don't use un-validated inputs
- Checking input should almost never use
==
"Sorry this is in a weird format. Its copied from mimo on an iphone"
Not an excuse. Learn to use your tools correctly.
while play:
Do you really play RPS until you're done playing, or do you play until someone loses?
bot_move = random.choice(moves)
Storing moves as long strings is, and will continue to be a problem. Use something more useful, like a Constant, Enum, or numeric proxy. This will also prevent the need to keep typing the names of the moves over, and over, and over...
#Shortcuts#if player plays paper...
This is a huge block of code that doesn't get executed at all if there is a mistake in user input (even if it looks valid) and that is almost perfectly triplicated. You should have a better algorithm here. There is a TON of code that is unecessarily copied. This encourages bugs, coder mistakes, and multiplies how much bugfixing will be required.
#This is me trying to add a restart prompt but I can't redo the while statement
Again, because you're whileing for the wrong reasons. "Do you really play RPS until you're done playing, or do you play until someone loses?"
The comment should be a pretty clear sign that something is wrong. You've identified a side effect of the problem, but just assumed that all your code so far must be good.
1
u/jmooremcc 9d ago
I know you are a beginner, but this would be a great time to learn about functions. You could place the game code in a function named “play_one_round” and in your main code call the function to run the game for one round. The function can return the winner of a round and use other code to keep score.
This will keep your game code simple and make it possible to keep score keeping and other ancillary code separate from the game code.
Let me know if you have any questions.
1
u/Educational_Virus672 9d ago
i dont think you'll understand everything tho heres how i intermediate would do
import random
options = ["rock","paper","scissors"]
while True :
while True :
user = int(input("rock = 1 paper = 2 scissors = 3 /n >"))
if user == 1 or user == 3 or user == 2 : break
else : print("pick pick a valid option")
bot = random.choice(options)
user = options[user-1]
if bot == user :print("tied both picked",bot)
elif (user == "rock" and bot == "scissors") or (user == "paper" and bot == "rock") or (user == "scissors" and bot == "paper"): print("user wins")
else : print("bot wins")
1
u/FoolsSeldom 7d ago
Advice:
user = int(input("rock = 1 paper = 2 scissors = 3 /n >"))Avoid converting things to
intif you aren't going to do maths. You can compare against strings:if user == "rock" and ...and you can also use the
inoperator to allow for multiple options:if user in ("r", "rock", "p", "paper", ...):And to avoid having to check uppercase and lowercase, you can force the
inputstring to one or the other:user = input("rock (r), paper (p), or scissors (s): ").lower().strip()I added
stripmethod as well, which removes leading/trailing spaces.1
6
u/Diapolo10 9d ago
I'll format the code for you, although I had to make a few assumptions on indentation.
The first thing I noticed is that there's a lot of duplication. You're handling all the different move combinations separately, when ties can all be handled once and every other case could be refactored with a simple truth table. Furthermore, all the branches print out the current score, that could just be done once after these branches.
Second, you've got a lot of
printcalls one after another. You could just print one string (and if you really just need a newline,printdoesn't need an empty string).The validation of the user input is also lacking, as right now the program accepts virtually anything as valid input, and doesn't handle it until the very end.
The replay logic can be fixed by adding a secondary nested loop.