I recently practiced python and I was finding myself get involved with a lot of if statements for a simple rock paper scissors game it looks like this: and my question is how i get my code more efficient and more friendly to write and read
while True:
player_choice = raw_input("\n1-Rock\n2-Paper\n3-Scissors\n{} choose a number:".format(name))
player_choice = int(player_choice)
if player_choice == 1:
player_choice = Choices.rock
if player_choice == 2:
player_choice = Choices.paper
if player_choice == 3:
player_choice = Choices.scissors
# Getting the cpu choice.
cpu_choice = random.randint(1, 3)
if cpu_choice == 1:
cpu_choice = Choices.rock
if cpu_choice == 2:
cpu_choice = Choices.paper
if cpu_choice == 3:
cpu_choice = Choices.scissors
if player_choice == cpu_choice:
print"\n Its a Tie!\n!"
if player_choice == Choices.paper and cpu_choice == Choices.rock:
print"\n Congratulations!\n{} you won!".format(name)
if player_choice == Choices.scissors and cpu_choice == Choices.paper:
print"\n Congratulations!\n{} you won!".format(name)
if player_choice == Choices.rock and cpu_choice == Choices.scissors:
print"\n Congratulations!\n{} you won!".format(name)
if cpu_choice == Choices.scissors and player_choice == Choices.paper:
print"\n Too bad!\n{} you lost!".format(name)
if cpu_choice == Choices.paper and player_choice == Choices.rock:
print"\n Too bad!\n{} you lost!".format(name)
if cpu_choice == Choices.rock and player_choice == Choices.scissors:
print"\n Too bad!\n{} you lost!".format(name)*
Your if
statements can be replaced by dictionaries . For example, mapping an integer to a specific Choices
attribute can be done with a dictionary like this:
choices = {1: Choices.rock, 2: Choices.paper, 3: Choices.scissors}
Now you can use
player_choice = choices[player_choice]
and
cpu_choice = random.choice(choices.values())
From an encapsulation point of view, it should really be the responsibility of the Choices
object to handle this mapping. If you were to use an actual enum.Enum
object (requires Python 3 or the installation of the enum34
backport package ) then you could just use:
player_choice = Choices(player_choice)
but depending on how you defined Choices
, you could give it a __call__
method that basically uses the above mapping to give you the same result.
Next, you could use a dictionary to determine winners:
# if a player picks the key, and the opponent has picked the value,
# then the player wins.
wins_against = {
Choices.rock: Choices.scissors,
Choices.paper: Choices.rock,
Choices.scissors: Choices.paper,
}
then determine the winner:
if player_choice == cpu_choice:
print"\n Its a Tie!\n!"
elif wins_against[player_choice] == cpu_choice:
print"\n Congratulations!\n{} you won!".format(name)
else: # not the same, and not a win, so the player lost
print"\n Too bad!\n{} you lost!".format(name)
That mapping could also be part of your Choices
enumeration objects however; give those a wins_against
attribute:
if player_choice == cpu_choice:
print"\n Its a Tie!\n!"
elif player_choice.wins_against == cpu_choice:
print"\n Congratulations!\n{} you won!".format(name)
else:
print"\n Too bad!\n{} you lost!".format(name)
If you were to use the enum
library, the code could become:
from enum import Enum
class Choices(Enum):
rock = 1, 'scissors'
paper = 2, 'rock'
scissors = 3, 'paper'
def __new__(cls, value, win_against):
instance = object.__new__(cls)
instance._value_ = value
instance._win_against = win_against
return instance
@property
def win_against(self):
return type(self)[self._win_against]
while True:
options = '\n'.join(['{}-{}'.format(c.value, c.name) for c in choices])
player_choice = raw_input("\n\n{} choose a number:".format(
options, name))
try:
player_choice = int(player_choice)
player_choice = Choices(player_choice)
except ValueError:
print "Not a valid option, try again"
continue
cpu_choice = random.choice(list(Choices))
if player_choice is cpu_choice:
print"\n Its a Tie!\n!"
elif player_choice.wins_against is cpu_choice:
print"\n Congratulations!\n{} you won!".format(name)
else: # not the same, and not a win, so the player lost
print"\n Too bad!\n{} you lost!".format(name)
You should use if/elif/else statements - it will only compare the conditionals until a true value occurs. And you may want to put an error message if the user inputs some other value
if player_choice == 1:
player_choice = Choices.rock
elif player_choice == 2:
player_choice = Choices.paper
elif player_choice == 3:
player_choice = Choices.scissors
else:
print "Invalid choice"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.