# Week 4, Friday: Functions, indefinite loops

### review

Here is part of the up/down game from last time:

``````level = 10
while level > 0:
char = raw_input("char (u/d): " )
if char == "u":
level += 1
result = " level UP"
elif char == "d":
level -= 1
result = " level down"
else:
insult()
result = " "
print("."*level + (" (%2d)" % (level)) + result)
``````

Notice how `level` is changed somewhere in the loop. If `level` never changed in the loop, we would have an infinite loop. If you ever write a program with a `while` loop, and it seems to be taking a long time to run, you have probably created an infinite loop (use Cntrl-c to stop the program).

### getting input from the user

An indefinite loop is great for giving users a second (or third, fourth, etc) chance when entering data:

``````You are in a dimly lit computer room. A lab that is worth
50% of your grade is due in 4 hours. What do you want
to do?

1 Start work on your lab
2 Go play ultimate frisbee with your friends
3 Take a nap on the CS couches

---> 9
please enter an integer from 1 to 3
---> -3
please enter an integer from 1 to 3
---> 1
``````

If we wrote a `getChoice()` function, it could ask the user to enter a number and also check to make sure it is a valid number. Using a `while` loop, we just keep asking until we get a valid number.

In a program like the above adventure game, you could have lots of menus and choices for the user to make. Some menus might have 3 choices, others might have more or less. The `getChoice()` function would be more general and probably more useful if we passed in arguments for the low and high choices. Here's how it might be called from `main()`:

``````printmenu()
choice = getChoice(1,3)
if choice == 1:
stuff for choice 1 here
elif choice == 2:
stuff for choice 2 here
...
``````

Here's one way to write the `getChoice()` function:

``````def getChoice(low, high):
"""get valid input from user (in range low to high)"""

while True:
num = int(raw_input("---> "))
if num >= low and num <= high:
return num
print "please enter an integer from %d to %d " % (low, high)
``````

Note the `while True`. Here it is used as an infinite loop, so there must be another way out of this loop. Since this is a function, the `return num` statement is the way out -- the `return` statement ends the function, and it only ends when we know `num` is valid (in range from `low` to `high`). If the `return num` line is not run, because the input was invalid, the function just runs the print statement and then loops back to the start of the loop (the `raw_input()` line).

### math quiz -- a real program!

As you start writing programs with multiple functions, it is very important that you write and test each function, one at a time.

Let's write a math quiz program, that runs like this:

``````\$ python mathquiz.py

Welcome to MathQuiz v0.1!

What factor would you like to work on? 4
-------------------------
4 x 10? 40
....Correct!
-------------------------
4 x 4? 16
....Correct!
-------------------------
4 x 5? 24
....Nope. 4 x 5 = 20
-------------------------
4 x 10? 40
....Correct!
-------------------------
4 x 7? 28
....Correct!
-------------------------
4 x 8? 32
....Correct!
-------------------------

You got 5 out of 6 correct. Good work!
``````

I like this program because it's got almost everything we've talked about so far: functions, loops, branching, random, etc.

A few things to note about the program (which you would see, if you ran it a few times):

• forces user to enter a starting factor from 2-12
• chooses a random factor from 2-12 each time
• creates and asks question, outputs result (and answer if they got it wrong)
• keeps asking questions until the user gets 3-in-a-row correct
• keeps track of total correct, and total number of problems
• output message at the end depends on percentage correct

See if you can write this program, but start with just this for `main()`:

``````def main():
factor = 5
result = question(factor)
print result
``````

Write the `question()` function first, and make sure it works (test it!). And start simple: have `question()` create a random multiplication problem, ask the question and get the answer, and then return something that says whether the user answered correctly or not (return True or False, or 1/0, or "correct"/"incorrect").