简体   繁体   中英

How to get a lot of if statements more readable in Python

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM