0

Hi i am trying to make the program only accept the numbers 0, 4, 6, and 12, and not allow anything else to be inputted. So far i have been successful in only allowing certain integers to be entered, however i am having trouble with not allowing any letters to be entered. When a letter is entered, the entire program crashes. Please could you help me only allow integers to be entered? Thank you.

My code is below:

from random import randint 
def simul():
    dice = int(input("What sided dice would you like to roll? 4, 6 or 12? 0 to not roll:"))
    if dice != 4 and dice!=6 and dice!=12 and dice!=0:
        print('You must either enter 4, 6, or 12')
        simul()
    elif dice==0:
        exit()
    else:
        while dice !=0 and dice==4 or dice==6 or dice ==12 :
            print (randint(1,dice))
            dice = int(input("What sided dice would you like to roll? 4, 6 or 12? press 0 to stop."))
simul()
pythoner888
  • 19
  • 1
  • 5

4 Answers4

1

put it in a try catch block like so:

try:
    choice = int(raw_input("Enter choice 1, 2 or 3:"))
    if not (1 <= choice <= 3):
        raise ValueError()
except ValueError:
    print "Invalid Option, you needed to type a 1, 2 or 3...."
else:
    print "Your choice is", choice

copied from: limit input to integer only (text crashes PYTHON program)

miken32
  • 42,008
  • 16
  • 111
  • 154
1

A couple of things you could look for in your code:

  • using try/catch is the recommended way to test input for many reasons including knowing the exact cause of the error
  • you can reduce some of your ifs and elses by thinking a little more about how they are nested
  • having the function call itself and using a while loop isn't the best way, use one or the other
  • in your case, you don't really need to allow only integer input, what you're looking for is to only allow a 0, 4, 6, or 12, which you do with the if statement
from random import randint
def simul():
    while True:
        try:
            dice = int(input("What sided dice would you like to" \
                    " roll? 4, 6 or 12? 0 to not roll: "))
            if dice not in (4, 6, 12, 0):
                raise ValueError()
            break  # valid value, exit the fail loop
         except ValueError:
            print("You must enter either 4, 6, 12, or 0")

    if dice == 0:
        return 0

    print(randint(1, dice))
    return dice

if __name__ == '__main__':
    while simul() != 0:
        pass
zopieux
  • 2,854
  • 2
  • 25
  • 32
Joseph Hansen
  • 12,665
  • 8
  • 50
  • 68
  • ok, i see what you have done here. Very silly of me to not include the try and except function in the code. Thank you so much for this!!! – pythoner888 Dec 30 '14 at 18:06
  • 2
    You should try to avoid recursion when possible, because the stack will grow everytime there's an error. In this case, you could trivially use a loop instead. – Antoine Pietri Dec 30 '14 at 18:14
  • What @serialk said. Another way to improve the code (and address the stack issue) would be to code other ways to escape the program besides just entering 0, such as a timer or a counter that counts the number of times input is received. – Joseph Hansen Dec 30 '14 at 18:19
  • FYI, I updated my answer. It's been a while since I coded in Python. My original answer used `raw_input()` and `print` where as Python 3.0+ says the correct syntax is `input()` and `print()`. – Joseph Hansen Dec 30 '14 at 18:21
  • I updated your code to something a bit cleaner, using the neat `in foo` syntax for validation and an outer infinite loop as the "main" program. As said, using recursion would eventually crash your program. – zopieux Dec 31 '14 at 14:16
  • @Zopieux Thanks. The changes are helpful. I just meant to be similar to the OP. – Joseph Hansen Dec 31 '14 at 23:14
1

I would encapsulate the "constrained input" functionality into a separate, reusable function:

def constrained_int_input(prompt, accepted, toexit=0):
    msg = '%s? Choose %s (or %s to exit)' % (
       prompt, ', '.join(str(x) for x in sorted(accepted)), toexit)
   while True:
       raw = raw_input(msg)
       try:
           entered = int(raw)
       except ValueError:
           print('Enter a number, not %r' % raw)
           continued
       if entered == toexit or entered in accepted:
           return entered
       print('Invalid number: %r -- please enter a valid one' % entered)

Now you can call e.g

dice = constrained_int_input('What sided dice would you like to roll', (4,6,12))

whenever required and be sure that dice will end up with one of the accepted integers, including possibly the to-exit value of 0.

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
0
while True:
    x=input("4,6 or 12? 0 to not roll: ")
    if x.isalpha():
        print ("only numbers.")
        continue
    elif int(x)==0:
        print ("quiting..")
        break
    elif int(x)!=4 and int(x)!=6 and int(x)!=12:
        print ("Not allowed.")
    else:
        print (random.randint(1,int(x)))

Here is another method, use isalpha().

GLHF
  • 3,835
  • 10
  • 38
  • 83