Today's lab looks at nested loops and indefinite loops from Chapter 8 and more on finding errors.

### Mystery Point Game

Today, we are going to write a simple game where the user tries to find our mystery point in the graphics window. Lets first go through the program section by section:

• Opening comments and importing modules: In addition to math and graphics, we will also need to generate random numbers (to put our point at a random location), so, we have also included that module:
```# Mystery point game for Lab 9
# Lehman College, CUNY, Fall 2012

from graphics import *
from math import *
from random import *
```
• We will reuse the distance function from the previous lab:
```# Reuse the distance function we wrote for Lab 8:
def dist(p1,p2):
dist = sqrt((p1.getX()-p2.getX())**2 + (p1.getY() - p2.getY())**2)
return dist

```
• Set up the graphics window:
```def main():
w = GraphWin("Target Practice",500,500)
w.setCoords(-250,-250,250,250)
```
• We will use the built-in random number generator to give coordinates for our mystery points. See Chapter 9 for more discussion on random numbers:
```    #Generate a mystery point (at a random location):
x = randrange(-200,200)
y = randrange(-200,200)
print("x and y are:",x,y)
mysteryPoint = Point(x,y)
```
• Set up a Text object to display messages to the user. We changed the font size, since the default one is small and hard to read.
```    #Text to tell the user what's happening:
t = Text(Point(0,-210), "Click on the mystery point")
t.setSize(16)
t.draw(w)
```
• Save the point that the user clicked in the variable p. We display its distance to our mystery point in the IDLE shell:
```    #Get the point:
p = w.getMouse()
p.draw(w)
d = dist(mysteryPoint, p)
print("distance from mystery point is:", d)
```
• This loop repeats as long as the condition d > 20 holds. So, once the point clicked is within 20 of the mystery point, the loop ends. You can make the game harder (or easier) by decreasing (or increasing) 20. For example, if you change the 20 to 10, then the user has to click even closer to the mystery point to win. If you change the 20 to 100, then the game becomes much easier since they only have to be within 100 to win.
```    #Keep going until they click close to the point:
while d > 20:
p = w.getMouse()
p.draw(w)
d = dist(mysteryPoint, p)
print("distance from mystery point is:", d)
```
• Congratulate the user for finding the point and end the program nicely:
```    t.setText("Congratulations!  You found the mystery point!")

#keep the window up until the user clicks
w.getMouse()
w.close()

main()
```

Try running the program. How easy is it to win?

### Giving Hints

Could you find the point without peeking at the IDLE shell? To make the game a bit easier, we will add hints. The first hint will be to tell the user if they need to click more to the left (or right) to find the point. Here is the pseudocode:

```	if point clicked is to the left of mystery point
give message "Too far left"
else
give message "Too far right"
```
How can you tell if the point clicked is to the left of the mystery point? The x-coordinate tells how far left or right a point is, so, we compare the x-coordinates of the two points:
```        if p.getX() < mysteryPoint.getX():
t.setText("Click again! You were too far left")
else:
t.setText("Click again! You were too far right")
```

Now, add in the code that will give a hint to move up (or down) depending on where they clicked with respect to the mystery point. Your completed program should have a "left/right" hint and an "low/high" hint to make the game possible to do without looking at our diagonostics on the python shell.

Hint: Before the loop, set up another Text object, t2 to display the message about being too low or too high:

```    t2 = Text(Point(0,-230), "")
t2.setSize(16)
t2.draw(w)
```

### Finding Errors, II

In Lab 6, we looked at some common syntax errors and how to fix them. Most of those errors were missing punctuation (such at colons, quotes, or plus signs). Let's look at a few more errors that occur when using conditionals, loops, and functions:

```# errors2.py-- modified from Zelle
# recursions.py
#   A collection of simple recursive functions from Zelle, 2nd Edition
#   (Some also include looping counterparts).

def fact(n)
# returns factorial of n
if n == 0:
return 1
else
return n * fact(n-1

def reverse(s):
# returns reverse of string s
if s == "":
return s
elif:
return reverse(s[1:]) + s

def anagrams(s):
# returns a list of all anagrams of string s
if s == "":
return [s]
else:
ans = []
for w in anagrams(s[1:]):
for pos in range(len(w)+1):
ans.append(w[:pos]+s+w[pos:])
return ans

def loopFib(n):
# returns the nth Fibonacci number
curr = 1
prev = 1
for i in range(n-2):
curr, prev = curr+prev, curr
return curr

def main():
n = eval(input("Enter a number: "))
s = input("Enter a string: ")
print(n+"!= ", fact(n), "or, loopFig(n))
print(s, "reversed is: ", reverse(s))
print("\n anagrams: ", anagrams(s))

main()

```

Load the program into IDLE and run the program. A dialog box pops up and says "invalid syntax": We have seen this one before, it's a missing colon (":") at the end of the function definition. Add it in and run again. Again, we get an invalid syntax. What's wrong here? (Hint: same as the last one). Fix the error, and let's run the program again: This one is different. IDLE has highlighted the word def, and yet that seems to spelled correctly. A general rule to follow: if you do not see an error on the current line, look above (usually for missing quotes or closing parenthesis). On the previous line, the function call to fact() is missing the closing parenthesis. Add it, and run the program again: This one is a bit harder-- all the keywords are spelled correctly and there's no missing colons, parenthesis, or quotes. What's wrong? Python expected the word else (elif is only used when you need multiple tests in multi-way decision). Replace elif with else and try again: The message says: unexpected indent. The line does seem to be indented for no reason (i.e. it's not part of a block of code in a loop or decision construct). Remove the extra indent and continue: This is a common error. In plain English, it means that the end of the line ("EOL") was reached before the string finished. In other words, the string is missing its ending quotes. Add it in (right after the word or) and run the program again.

It now compiles! But we need to test it to make sure no run-time errors remain: When reading the traceback message (all the red text), go to the very last line and see what it says. The message says we cannot use + for 'int' and 'string'. We only used + once in the line to concatenate n to a string. Since we want n to eventually be a string and printed to the screen, let's change it to a string (by using the str() function):

```print(str(n)+"!= ", fact(n), "or", loopFig(n))
```

Running it again, a new run-time errors appears: The message says that IDLE cannot find loopFig(). Scanning through the file, it looks we misspelled it! The function is called loopFib(). Fix the misspelling in the main() and try again... Success! The program accepted input, processed it, and outputted it to the screen. Try with a couple of different inputs to test how it works.

If you finish early, you may work on the programming problems.