-1

I'm fairly new to programming in general and have been learning python3 for the last week or so. I tried building a dice roller and ran into an issue when asking the user if they wanted to repeat the roller or end the program.

import random as dice

d100 = dice.randint(1,100)
d20 = dice.randint(1,20)
d10 = dice.randint(1,10)
d8 = dice.randint(1,8)
d6 = dice.randint(1,6)
d4 = dice.randint(1,4)
d2 = dice.randint(1,2)

repeat = 'Y'
while repeat == 'Y' or 'y' or 'yes' or 'Yes':
    roll = (input('What would you like to roll? A d100, d20,  d10, d8, d6, d4, or d2?:'))
    quantity = (input('How many would you like to roll?'))
    quantity = int(quantity)
    if roll == 'd100':
        print('You rolled a: ' + str(d100 * quantity) + '!')

    elif roll == 'd20':
        print('You rolled a: ' + str(d20 * quantity) + '!')

    elif roll == 'd10':
        print('You rolled a: ' + str(d10 * quantity) + '!')

    elif roll == 'd8':
        print('You rolled a: ' + str(d8 * quantity) + '!')

    elif roll == 'd6':
        print('You rolled a: ' + str(d6 * quantity) + '!')

    elif roll == 'd4':
        print('You rolled a: ' + str(d4 * quantity) + '!')

    elif roll == 'd2':
        print('You rolled a: ' + str(d2 * quantity) + '!')        

    else:
        print('That is not an available die! Please select a die.')

    repeat = input('Would you like to continue?: ')
    if repeat == 'yes' or 'Y' or 'y' or 'Yes':
        continue

As of right now, despite what is input for the repeat variable it always continues even if it isn't "yes", "Y", "y", or "Yes". I'm sure the answer is simple and right in front of me but I'm stumped! Thanks in advance!

Owen Hall
  • 9
  • 2
  • 2
    It's a problem of precedence: `repeat == 'Y' or 'y' or 'yes' or 'Yes'` is interpreted as `(repeat == 'Y') or 'y' or 'yes' or 'Yes'` and then it tries to check whether `'y'` counts as true, which it does (it's a non-empty string). What you want is `repeat in ('Y', 'y', 'yes', 'Yes')` – Jiří Baum Nov 01 '21 at 02:25
  • 1
    You didn't ask, but I'll note that your representation of rolling dice is not altogether faithful to how dice usually work: rolling a D6 five times ought to give you _five outcomes of five independent rolls of a D6_ not _five multiplied by whatever number you rolled the first time_, which is what you currently return. (i.e., D6 quantity 5 should invoke `dice.randint(1,6)` five times.) – msanford Nov 01 '21 at 02:31
  • 1
    @msanford That's very true, I'll have to work on making it more of an accurate representation now that the loop is fixed, thank you! – Owen Hall Nov 01 '21 at 02:42
  • @OwenHall Pleasure! A list comprehension might be a fun way to start, but there are many ways to do this( e.g., `[dice.randint(1,6) for _ in range(quantity-1)]` which will return a list of rolls `[1, 4, 6, 1, 3]`) – msanford Nov 01 '21 at 19:54

2 Answers2

2

It's a problem of precedence: repeat == 'Y' or 'y' or 'yes' or 'Yes' is interpreted as (repeat == 'Y') or 'y' or 'yes' or 'Yes' and then it tries to check whether 'y' counts as true, which it does (it's a non-empty string).

What you want is while repeat in ('Y', 'y', 'yes', 'Yes'):

By the way, you don't need the if statement at the end of the loop since it will exit automatically if repeat is something other than 'Y', 'y', 'yes', or 'Yes'.

Jiří Baum
  • 6,697
  • 2
  • 17
  • 17
0

Two things

continue means go to the top of the loop (and then check whether to re-enter it), not guaranteed to go through the loop again. It might be better named skip because it really means "skip the rest of this iteration". Hence you don't need if ... continue because you're already at the end of the iteration.

The real loop control is what follows while. You've made a common mistake by assuming Python can group those or operators as one set of options opposite the ==. It can't. Only the first string is compared to repeat and the others are treated as individual conditions. A string on its own is True as long as it's not empty. Hence Python reads that as

while repeat is 'Y', or 'y' is not empty, or 'Yes' is not empty, or 'yes' is not empty

Since all three of those strings are by definition not empty, it doesn't matter if repeat is 'Y', the whole condition will always be True.

The way to do multiple options for equality is

while repeat in ('Yes', 'yes', 'Y', 'y')

This means that repeat must appear in that list of options.

Note that you can simplify by normalizing or casefolding repeat.

while repeat.upper() in ('Y', 'YES')

Or be even simpler and less strict

while repeat.upper().startswith('Y')

You should also strip repeat to further eliminate user error of whitespace:

while repeat.strip().upper().startswith('Y')

Then you begin to arrive at a best practice for user-ended loops :)

Luke Sawczak
  • 313
  • 4
  • 14