If Else Statement Ask Question Again
iii.3.1. Simple while Loops¶
Other than the fox with using a return statement inside of a for loop, all of the loops and so far have gone all the way through a specified list. In whatever case the for loop has required the use of a specific list. This is oft too restrictive. A Python while loop behaves quite similarly to common English usage. If I say
While your tea is too hot, add a chip of ice.
Presumably you would test your tea. If it were likewise hot, you lot would add a little ice. If you test again and information technology is however as well hot, you would add together water ice again. As long as you tested and found it was true that your tea was too hot, you would go back and add more ice. Python has a similar syntax:
whilecondition:- indentedBlock
Setting up the English language case in a similar format would be:
- while your tea is also hot :
- add a fleck of ice
To brand things physical and numerical, suppose the post-obit: The tea starts at 115 degrees Fahrenheit. You desire it at 112 degrees. A chip of ice turns out to lower the temperature i caste each time. You test the temperature each time, and also impress out the temperature before reducing the temperature. In Python you could write and run the code below, saved in example program cool.py:
temperature = 115 while temperature > 112 : # commencement while loop lawmaking impress ( temperature ) temperature = temperature - 1 print ( 'The tea is cool enough.' ) |
I added a final line after the while loop to remind y'all that execution follows sequentially after a loop completes.
If you play reckoner and follow the path of execution, y'all could generate the following table. Retrieve, that each time you reach the cease of the indented block later the while heading, execution returns to the while heading for another examination:
| Line | temperature | Comment |
|---|---|---|
| one | 115 | |
| 2 | 115 > 112 is true, practise loop | |
| 3 | prints 115 | |
| 4 | 114 | 115 - 1 is 114, loop dorsum |
| 2 | 114 > 112 is true, exercise loop | |
| three | prints 114 | |
| 4 | 113 | 114 - 1 is 113, loop back |
| 2 | 113 > 112 is true, do loop | |
| iii | prints 113 | |
| 4 | 112 | 113 - 1 is 112, loop back |
| 2 | 112 > 112 is false, skip loop | |
| half dozen | prints that the tea is cool |
Each time the end of the indented loop body is reached, execution returns to the while loop heading for another test. When the test is finally false, execution jumps past the indented torso of the while loop to the next sequential argument.
A while loop generally follows the design of the successive modification loop introduced with for -each loops:
initialization
whilecontinuationCondition:exercise main activeness to be repeated
prepare variables for the adjacent time through the loop
Test yourself: Following the code. Figure out what is printed. :
i = four while i < nine : print ( i ) i = i + 2 Cheque yourself by running the example program testWhile.py .
Annotation
In Python, while is not used quite like in English. In English you could mean to stop as before long equally the condition you want to test becomes imitation. In Python the test is but made when execution for the loop starts (or starts again), non in the middle of the loop.
Predict what will happen with this slight variation on the previous case, switching the society in the loop body. Follow information technology carefully, ane step at a time.
i = iv # variation on testWhile.py while ( i < 9 ): i = i + 2 print ( i ) |
Check yourself by running the case plan testWhile2.py .
The sequence guild is of import. The variable i is increased before it is printed, so the first number printed is 6. Another common error is to presume that x will not exist printed, since 10 is past ix, but the test that may stop the loop is not made in the center of the loop. One time the body of the loop is started, it continues to the stop, even when i becomes 10.
| Line | i | Comment |
|---|---|---|
| i | 4 | |
| 2 | 4 < ix is true, practise loop | |
| 3 | half-dozen | 4+2=half dozen |
| 4 | print 6 | |
| 2 | half dozen < 9 is true, exercise loop | |
| 3 | eight | 6+2= 8 |
| four | print eight | |
| two | 8 < 9 is true, do loop | |
| 3 | 10 | 8+ii=x No test here |
| 4 | print 10 | |
| 2 | 10 < 9 is imitation, skip loop |
Predict what happens in this related little plan:
nums = list () i = 4 while ( i < 9 ): nums . append ( i ) i = i + 2 print ( nums ) Bank check yourself by running the example plan testWhile3.py .
three.3.2. The Most General range Function¶
At that place is really a much simpler way to generate the previous sequences like in testWhile3.py , using a farther variation of the range part. Enter these lines separately in the Vanquish. As in the simpler applications of range , the values are only generated one at a fourth dimension, as needed. To see the entire sequence at once, convert the sequence to a list before printing:
nums = range ( iv , 9 , 2 ) print ( listing ( nums )) The third parameter for the range function is the footstep size. Information technology is needed when the step size from one chemical element to the next is non one.
The virtually full general syntax is
range(start,pastEnd,step)
The value of the 2nd parameter is e'er past the terminal chemical element of the listing. Each element after the first in the list is step more than the previous one. Predict and endeavour in the Shell:
Really the range function is even more sophisticated than indicated past the while loop above. The step size can be negative. Try in the Shell:
Do you see how 0 is past the end of the listing?
Endeavour it: Make upwardly a range function call to generate the list of temperatures printed in the tea example, 115, 114, 113 . Test it in the Shell.
These ranges, like the simpler ranges that nosotros used earlier, are well-nigh often used as the sequence in a for loop heading:
for i in range ( x , 0 , - ane ): # countdown... print ( i ) impress ( 'Blastoff!' ) 3.three.3. Interactive while Loops¶
The earlier examples of while loops were called for their simplicity. Obviously they could have been rewritten with range function calls. Now lets try a more than interesting example. Suppose y'all want to let a user enter a sequence of lines of text, and desire to call up each line in a list. This could easily be washed with a uncomplicated repeat loop if you knew the number of lines to enter. For example, in readLines0.py , the user is prompted for the verbal number of lines to be entered:
lines = list () north = int ( input ( 'How many lines do you want to enter? ' )) for i in range ( n ): line = input ( 'Adjacent line: ' ) lines . append ( line ) print ( 'Your lines were:' ) # cheque now for line in lines : print ( line ) The user may want to enter a agglomeration of lines and not count them all ahead of time. This means the number of repetitions would not be known ahead of time. A while loop is advisable here. At that place is still the question of how to test whether the user wants to proceed. An obvious but verbose way to do this is to ask earlier every line if the user wants to go on, every bit shown beneath and in the case file readLines1.py . Read it so run it:
lines = listing () testAnswer = input ( 'Press y if y'all want to enter more lines: ' ) while testAnswer == 'y' : line = input ( 'Adjacent line: ' ) lines . append ( line ) testAnswer = input ( 'Press y if you desire to enter more lines: ' ) impress ( 'Your lines were:' ) for line in lines : print ( line ) Meet the two statements setting testAnswer : one before the while loop and one at the bottom of the loop trunk.
Note
The information must be initialized before the loop, in lodge for the first test of the while condition to work. Also the examination must piece of work when you loop back from the finish of the loop trunk. This means the data for the examination must also be prepare upwards a 2d fourth dimension, in the loop torso (commonly equally the action in the last line of the loop). It is easy to forget the second time!
The readLines1.py code works, merely it may exist more than abrasive than counting ahead! 2 lines must be entered for every one yous actually desire! A applied alternative is to use a sentinel: a piece of data that would not make sense in the regular sequence, and which is used to signal the finish of the input. You could hold to use the line DONE! Even simpler: if you presume all the real lines of information volition actually have some text on them, use an empty line as a lookout. (If you recollect near information technology, the Python Shell uses this arroyo when you lot enter a argument with an indented torso.) This mode you only need to enter one extra (very simple) line, no matter how many lines of real data yous accept.
What should the while condition be now? Since the sentinel is an empty line, you might think line == '' , but that is the termination condition, not the continuation condition: You demand the opposite status. To negate a condition in Python, you may use not , like in English language,
Of grade in this situation at that place is a shorter manner,
Run the case plan readLines2.py , shown below:
lines = list () print ( 'Enter lines of text.' ) print ( 'Enter an empty line to quit.' ) line = input ( 'Next line: ' ) # initalize earlier the loop while line != '' : # while NOT the termination status lines . suspend ( line ) line = input ( 'Next line: ' ) # !! reset value at cease of loop! impress ( 'Your lines were:' ) for line in lines : print ( line ) Over again the data for the test in the while loop heading must be initialized before the first time the while statement is executed and the examination data must likewise be made set up inside the loop for the test later on the body has executed. Hence y'all encounter the statements setting the variable line both before the loop and at the end of the loop body. It is easy to forget the second place inside the loop!
Subsequently reading the rest of this paragraph, comment the last line of the loop out, and run it once more: It will never stop! The variable line will forever have the initial value you gave information technology! You actually can finish the program by entering Ctrl-C . That ways concur the Ctrl key and press c .
Note
As you finish coding a while loop, it is good practice to always double-check: Did I make a modify to the variables, inside the loop, that will eventually make the loop condition Imitation ?
The earliest while loop examples had numerical tests and the code to become ready for the side by side loop only incremented a numerical variable past a stock-still amount. Those were unproblematic examples but while loops are much more than general! In the interactive loop nosotros take seen a continuation status with a string test, and getting ready for the next time through the loop involves input from the user.
Some of the exercises that follow involve interactive while loops. Others were delayed until here just because they have a wider variety of continuation condition tests and means to prepare for the next time through the loop. What is consistent is the general steps to think of and questions to enquire yourself. They continue on applying! Keep these in heed!
- the need to see whether there is a kind of repetition, even without a stock-still collection of values to work through
- to recollect from the specific situation and figure out the continuation status that makes sense for your loop
- to call up what specific processing or results you desire each time through the loop, using the same lawmaking
- to effigy out what supporting code yous demand to make you ready for the next time through the loop: how to make the same results lawmaking have new data values to procedure each time through, and somewhen reach a stopping point.
Detecting the need for while statements: Like with planning programs needing``for`` or if statements, you want to exist able to translate English descriptions of issues that would naturally include while statements. What are some words or phrases or ideas that suggest the apply of these statements? Think of your own and and so compare to a few I gave: [i]
3.3.3.1. Interactive Sum Exercise¶
Write a program sumAll.py that prompts the user to enter numbers, 1 per line, ending with a line containing only 0, and go along a running sum of the numbers. Only print out the sum after all the numbers are entered (at to the lowest degree in your last version). Practise non create a list! Each fourth dimension you read in a number, you can immediately utilize it for your sum, and then be done with the number just entered.
three.iii.3.2. Safe Number Input Exercise¶
* In that location is an issue with reading in numbers with the input statement. If you brand a typo and enter something that cannot be converted from a string to the right kind of number, a naive programme will bomb. This is avoidable if y'all examination the string and repeat if the string is illegal. In this exercise write safe utility function replacements for the input part that work to read in a whole number, an integer or a decimal number.
All parts refer to the previous Is Number String Practise. Part a. refers to the introduction in the previous do. Parts b. and c. refer to functions in the solution, isNumberStr.py , of the previous practice. Make sure you look back at these outset.
Save the example safeNumberInputStub.py every bit safeNumberInput.py , and complete it. It contains headings and documentation strings for the functions in each part of this practise.
- This function considers the simplest instance, where you are trying to enter a whole number. Consummate the definition of the function
safeWholeNumber. - Complete the function
safeInt. This hands parallels part a. if yous copy in and use the function (non method)isIntegerStr. - Complete the function
safeDecimal. This easily parallels part b. if you copy in and use the functionisDecimalStr.
3.3.three.3. Savings Exercise¶
The idea here is to see how many years it volition take a bank account to grow to at to the lowest degree a given value, assuming a fixed annual involvement. Write a program savings.py . Prompt the user for three numbers: an initial rest, the annual percentage for interest equally a decimal, like .04 for iv%, and the final residual desired.
All the monetary amounts that you print should exist rounded to exactly two decimal places. Start by press the initial balance this manner. For instance, if the initial residue was entered equally 123.5, it should exist reprinted past your program as 123.fifty. As well print the balance each year until the desired amount is reached or passed. The first balance at or past the target should be the last one printed.
The math: The amount side by side year is the amount now times (ane + involvement fraction), so if I have $500 now and the interest charge per unit is .04, I have $500*(1.04) = $520 after one yr and afterwards 2 years I have, $520*(1.04) = $540.eighty....
For example, if I respond to the prompts, and enter into the programme a $500 starting rest, .04 involvement rate and a target of $550, the program prints:
500.00 520.00 540.80 562.43 3.3.3.4. Strange Sequence Exercise¶
* Recall Strange Function Exercise and its jumpFunc.py which contains the function jump : For any integer n, jump(northward) is n//2 if north is even, and 3*northward+1 if northward is odd.
Y'all tin can offset with one number, say n = three, and go on applying the bound office to the concluding number given, and see how the numbers bound effectually!
jump ( 3 ) = 3 * iii + 1 = 10 ; jump ( 10 ) = 10 // 2 = v ; jump ( 5 ) = 3 * 5 + 1 = 16 ; jump ( 16 ) = 16 // ii = eight ; jump ( viii ) = 8 // 2 = four ; spring ( iv ) = 4 // 2 = 2 ; jump ( two ) = ii // two = 1 This process of repeatedly applying the same role to the most contempo result is called office iteration. In this instance you see that iterating the spring function, starting from n=three, eventually reaches the value 1.
It is an open research question whether iterating the jump function from an integer northward will eventually reach i, for every starting integer n greater than one. Researchers have but institute examples of n where it is true. Still, no general argument has been made to apply to the infinite number of possible starting integers.
In this exercise you iterate the leap function for specific starting values n, until the result is one.
-
Save case
jumpSeqStub.pyevery bitjumpSeq.pyand complete the missing function bodies. If you coded the functionboundbefore injumpFunc.py, you can copy it. You can complete eitherprintJumpsorlistJumpsfirst, and test earlier completing the other. Hint [two] -
Afterward you lot have finished and saved
jumpSeq.pycopy it and save the file asjumpSeqLengths.py.Starting time modify the primary method and so it prompts the user for a value of northward, and so prints just the length of the iterative sequence from listJumps(n). Hint [3]
Then elaborate the programme so it prompts the user for two integers: a lowest starting value of n and a highest starting value of n. For all integers n in the range from the lowest start through the highest beginning, including the highest, print a judgement giving the starting value of n and the length of the listing from
listJumps(n). An case run:Enter everyman start: iii
Enter highest first: six
Starting from three, jump sequence length 8.
Starting from iv, leap sequence length three.
Starting from v, jump sequence length 6.
Starting from half-dozen, leap sequence length 9.
3.3.4. Graphical Applications¶
Another identify where a while loop could be useful is in interactive graphics. Suppose y'all want the user to be able to create a Polygon by clicking on vertices they cull interactively, simply y'all practice not want them to have to count the number of vertices ahead of time. A while loop is suggested for such a repetitive process. Every bit with inbound lines of text interactively, there is the question of how to indicate that you are done (or how to indicate to proceed). If you make only a certain region exist allowed for the Polygon, so the lookout man can exist a mouse click outside the region. The earlier interactive color choice case already has a method to bank check if a mouse click is inside a Rectangle, so that method tin be copied and reused.
Creating a polygon is a unified activity with a articulate consequence, so let'due south ascertain a function. It involves a purlieus rectangle and mouse clicks in a GraphWin, and may also return the Polygon constructed. Read the following outset:
def polyHere ( rect , win ): ''' Draw a polygon interactively in Rectangle rect, in GraphWin win. Collect mouse clicks inside rect into the vertices of a Polygon, and always depict the Polygon created so far. When a click goes exterior rect, finish and render the final polygon. The Polygon ends upward drawn. The method draws and undraws rect. ''' It is useful to start by thinking of the objects needed, and requite them names.
- A Polygon is needed. Telephone call it
poly. - A list of vertices is needed. Call it
vertices. I need to append to this list. It must be initialized first. - The latest mouse click point is needed. Call it
pt.
Certainly the overall process will exist repetitious, choosing point afterward bespeak. Still information technology may not be at all articulate how to make an effective Python loop. In challenging situations like this it is oftentimes useful to imagine a concrete situation with a limited number of steps, so each stride can be written in sequence without worrying about a loop.
For case to get upwards to a triangle (3 vertices in our list and a quaternary mouse click for the lookout man), you might imagine the post-obit sequence, undrawing each old polygon before the next is displayed with the latest mouse click included:
rect . setOutline ( 'red' ) rect . describe ( win ) vertices = list () pt = win . getMouse () vertices . append ( pt ) poly = Polygon ( vertices ) poly . draw ( win ) # with one betoken pt = win . getMouse () poly . undraw () # missing latest point vertices . suspend ( pt ) poly = Polygon ( vertices ) poly . draw ( win ) # with two points pt = win . getMouse () poly . undraw () # missing latest point vertices . append ( pt ) poly = Polygon ( vertices ) poly . describe ( win ) # with three points pt = win . getMouse () # assume outside the region rect . undraw () return poly There is a fine point here that I missed the first fourth dimension. The vertices of an existing Polygon practice non get mutated in this organisation. A new Polygon gets created each fourth dimension with the new vertex listing. The old Polygon does non go away automatically, and extraneous lines announced in the flick if the old polygon is non explicitly undrawn each time before a new version is redrawn with an extra vertex. The last Polygon you draw should be visible at the end, so in the case in a higher place where I was assuming the third click was the last for the triangle, I did not undraw the Polygon.
The timing for each undraw needs to be after the next mouse click and presumably before the revised Polygon is created, and then it could exist earlier or afterwards the line vertices.suspend(pt) . I arbitrarily chose for it to get earlier the vertices list is changed. The rest of the order of the lines is pretty well fixed by the basic logic.
If you think of the repetitions through a large number of loops, the process is substantially circular (as suggested by the discussion 'loop'). The body of a loop in Python, even so, is written as a linear sequence: one with a starting time line and a concluding line, a beginning and an end. We tin can cutting a circular loop anywhere to go a piece with a commencement and an end. In practice, the place you cut the loop for Python has one primary constraint: The processing in Python from the end of one time through the loop to the beginning of the next loop is separated by the exam of the status in the heading. The continuation condition in the while heading must brand sense where you cut the loop.
It can aid to look at a concrete example sequence, like the steps listed above for creating a triangle, only now assuming we do not know how many vertices will exist chosen. The continuation condition is for pt to exist in the rectangle, so using the previously written function isInside , the loop heading volition be
while isInside ( pt , rect ): With this condition in mind, look for where to separate to loop. It needs to be later a new pt is clicked (so it tin be tested) and before the next Polygon is created (so it does not include the sentinel bespeak past error). In detail, with the sequence higher up, expect and see that the split could go before or afterwards the poly.undraw() line. Exercise Moving Undraw considers the example where the split up goes before this line. I volition proceed with the choice of splitting into a Python loop after the undraw line. This makes the loop be
while isInside ( pt , rect ): vertices . append ( pt ) poly = Polygon ( vertices ) poly . depict ( win ) pt = win . getMouse () poly . undraw () If you follow the total sequence of required steps to a higher place for making the concrete triangle, you run into that this total sequence for the loop is merely repeated twice. The final fourth dimension there is no poly.undraw() step. I could redo the loop moving the undraw line to the top, which caused different issues (Practise Moving Undraw below). Instead think how to make information technology work at the end of the final time through the loop....
There are several possible approaches. You desire the undraw line every fourth dimension except for the last time. Hence it is a statement you want sometimes and not others. That suggests an if statement. The times you want the undraw are when the loop will repeat once more. This is the aforementioned as the continuation condition for the loop, and you have just read the next value for pt ! You could merely add a condition in front of the last line of the loop:
if isInside ( pt , rect ): poly . undraw () I find this option unaesthetic: it means duplicating the continuation test twice in every loop.
Instead of avoiding the undraw as you go out the loop, some other selection in this case is to disengage it: just redepict the polygon one concluding time beyond the loop. This only needs to be done once, not repeatedly in the loop. Then the repetitious lines collapse neatly into the loop.
If you look at the overall concrete sequence for the triangle, not all the lines are in the loop. You must advisedly include the lines both that come before the loop and those that come after the loop. Brand sure these lines are non put in the loop, but earlier or afterward, equally indicated past the concrete sequence in the instance. In the end the entire office is:
def polyHere ( rect , win ): ''' Draw a polygon interactively in Rectangle rect, in GraphWin win. Collect mouse clicks inside rect into the vertices of a Polygon, and ever describe the Polygon created so far. When a click goes outside rect, stop and return the concluding polygon. The Polygon ends up drawn. The method draws and undraws rect. ''' rect . setOutline ( "red" ) rect . describe ( win ) vertices = list () pt = win . getMouse () while isInside ( pt , rect ): vertices . append ( pt ) poly = Polygon ( vertices ) poly . draw ( win ) pt = win . getMouse () poly . undraw () poly . draw ( win ) rect . undraw () return poly Make sure you understand: Follow this code through, imagining 3 mouse clicks within rect and and so one click outside of rect. Compare the steps to the ones in the concrete sequence written out above and encounter that the friction match (aside from the terminal canceling undraw and draw of poly ).
This part is illustrated in the instance program makePoly.py . Other than standard graphics case code, the master plan contains:
rect1 = Rectangle ( Bespeak ( 5 , 55 ), Point ( 200 , 120 )) poly1 = polyHere ( rect1 , win ) poly1 . setFill ( 'green' ) rect2 = Rectangle ( Point ( 210 , 50 ), Betoken ( 350 , 350 )) poly2 = polyHere ( rect2 , win ) poly2 . setOutline ( 'orangish' ) Every bit you can meet, the returned polygons are used to make color changes, just as an illustration.
In earlier animation examples a while loop would also accept been useful. Rather than continuing the animation a fixed number of times, information technology would exist nice for the user to indicate by a mouse click when she has watched long plenty. Thus far the simply manner to utilise the mouse has been with getMouse() . This is not going to piece of work in an animation, because the computer stops and waits for a click with getMouse() , whereas the blitheness should continue until the click.
In full-fledged graphical systems that respond to events, this is no problem. Zelle'southward graphics is built on pinnacle of a capable event-driven system, and in fact, all mouse clicks are registered, even outside calls to getMouse() .
As an case, run example plan randomCirclesWhile.py . Be sure to follow the prompt proverb to click to start and to finish.
Bated from the prompts, the difference from the previous randomCircles.py program is the replacement of the original simple repeat loop heading
past the following initialization and while loop heading:
while win . checkMouse () == None : #NEW* The graphics module remembers the last mouse click, whether or not it occurred during a call to getMouse() . A way to cheque if the mouse has been clicked since the concluding call to getMouse() is checkMouse() . It does not look for the mouse equally in getMouse() . Instead it returns the remembered mouse click - the almost recent mouse click in the past, unless there has been no mouse click since the terminal call to getMouse or checkMouse. In that example checkMouse() returns None (the special object used to betoken the lack of a regular object).
The checkMouse method allows for a loop that does not stop while waiting for a mouse click, but goes on until the heading examination detects that the mouse was clicked.
A similar elaboration can be made for the other examples of animation, similar bounce1.py . In bounceWhile.py I modified bounce1.py to have a while loop in place of the for-loop repeating 600 times. Run it. The only slight added modification here was that win was not originally a parameter to bounceInBox , so I included it. Expect at the source code for bounceWhile.py , with the few changes marked NEW.
In bounce2.py I besides made a more interesting change to the initialization, and then the initial direction and speed of the mouse are determined graphically by the user, with a mouse click. Try instance plan bounce2.py .
The plan includes a new utility function to assistance determine the initial (dx, dy) for the blitheness. This is done by calculating the move necessary to get from one point (where the ball is in this program) to another (specified past a user's mouse click in this programme). :
def getShift ( point1 , point2 ): # NEW utility function '''Returns a tuple (dx, dy) which is the shift from point1 to point2.''' dx = point2 . getX () - point1 . getX () dy = point2 . getY () - point1 . getY () return ( dx , dy ) Since the function calculates both a change in x and y, it returns a tuple .
A straightforward interactive method, getUserShift , is wrapped effectually this role to get the user's selection, which ultimately returns the same tuple:
def getUserShift ( point , prompt , win ): #NEW direction option '''Return the change in position from the point to a mouse click in win. First display the prompt string nether bespeak.''' text = Text ( Point ( point . getX (), 60 ), prompt ) text . draw ( win ) userPt = win . getMouse () text . undraw () render getShift ( point , userPt ) In the new version of the main driver, bounceBall , excerpted beneath, this interactive setting of (dx, dy) is used. Note the multiple assignment statement to both dx and dy, set from the tuple returned from getUserShift . This shift would generally be much also much for a single animation step, then the actual values passed to bounceBall are scaled way down past a factor scale .
heart = Point ( win . getWidth () / 2 , win . getHeight () / 2 ) #NEW primal starting point ball = makeDisk ( center , radius , win ) #NEW interactive direction and speed setting prompt = ''' Click to bespeak the management and speed of the ball: The further you lot click from the brawl, the faster information technology starts.''' ( dx , dy ) = getUserShift ( center , prompt , win ) calibration = 0.01 # to reduce the size of blitheness steps bounceInBox ( brawl , dx * scale , dy * calibration , xLow , xHigh , yLow , yHigh , win ) The bounceInBox method has the same change to the loop as in the randomCircles.py example. The method then requires the GraphWin , win , equally a further parameter, since checkMouse is a GraphWin method.
Yous can look in Idle at the full source code for bounce2.py if you like. The changes from bounce1.py are all marked with a comment starting with #NEW , and all the major changes have been described to a higher place.
In the examples then far of the use of checkMouse() , we take merely used the fact that a point was clicked, non which point. The next example version, bounce3.py , does utilise the location of mouse clicks that are read with checkMouse() to change the direction and speed of the ball. Try information technology.
This version just slightly modifies the central animation function, bounceInBox , simply wraps it in another looping function that makes the direction and speed of the ball change on each mouse click. Hence the mouse clicks detected in bounceInBox demand to be remembered and then returned after the chief animation loop finishes. That requires a proper name, pt , to exist given to the last mouse click, so information technology tin can exist remembered. This means modifying the master blitheness loop to initialize the variable pt before the loop and reset it at the end of the loop, much as in the utilize of getMouse() for the interactive polygon creation. That explains the first iii NEW lines and the concluding 2 NEW lines in the revised bounceInBox :
def bounceInBox ( shape , dx , dy , xLow , xHigh , yLow , yHigh , win ): ''' Animate a shape moving in jumps (dx, dy), bouncing when its center reaches the low and high ten and y coordinates. The animation stops when the mouse is clicked, and the last mouse click is returned.''' delay = . 001 pt = None #NEW while pt == None : #NEW shape . move ( dx , dy ) center = shape . getCenter () x = center . getX () y = center . getY () isInside = True #NEW if x < xLow or 10 > xHigh : dx = - dx isInside = Faux #NEW if y < yLow or y > yHigh : dy = - dy isInside = Imitation #NEW time . slumber ( delay ) if isInside : # NEW don't mess with dx, dy when exterior pt = win . checkMouse () #NEW return pt #NEW def moveInBox ( shape , stopHeight , xLow , xHigh , yLow , yHigh , win ): #NEW '''Shape bounces in win so its center stays within the depression and high 10 and y coordinates, and changes direction based on mouse clicks, terminating when at that place is a click above stopHeight.''' scale = 0.01 pt = shape . getCenter () # starts motionless while pt . getY () < stopHeight : ( dx , dy ) = getShift ( shape . getCenter (), pt ) pt = bounceInBox ( shape , dx * calibration , dy * scale , xLow , xHigh , yLow , yHigh , win ) def makeDisk ( center , radius , win ): '''Render a red deejay that is drawn in win with given middle and radius.''' disk = Circle ( heart , radius ) disk . setOutline ( "red" ) deejay . setFill ( "red" ) disk . draw ( win ) return disk def getShift ( point1 , point2 ): '''Returns a tuple (dx, dy) which is the shift from point1 to point2.''' dx = point2 . getX () - point1 . getX () dy = point2 . getY () - point1 . getY () return ( dx , dy ) def bounceBall (): '''Brand a ball bounciness around the screen, and react to mouse clicks.''' win = GraphWin ( 'Ball Bounce 3' , 290 , 290 ) win . yUp () #NEW to marking and label the area where a click stops the program lineHeight = win . getHeight () - 40 textHeight = win . getHeight () - 20 Line ( Point ( 0 , lineHeight ), Point ( win . getWidth (), lineHeight )) . draw ( win ) prompt = 'Click higher up the line to stop \n or beneath to move toward the click.' Text ( Betoken ( win . getWidth () / two , textHeight ), prompt ) . draw ( win ) radius = x xLow = radius # centre is separated from the wall by the radius at a bounce xHigh = win . getWidth () - radius yLow = radius yHigh = lineHeight - radius #NEW lower top to bouncing limits center = Indicate ( win . getWidth () / 2 , lineHeight / 2 ) ball = makeDisk ( center , radius , win ) moveInBox ( brawl , lineHeight , xLow , xHigh , yLow , yHigh , win ) #NEW win . close () bounceBall () I initially fabricated merely the changes discussed so far (not the ones involving the new variable isInside ). The variable isInside was in response to a issues that I will discuss after introducing the simple function that wraps around bounceInBox :
Each time the mouse is clicked, the ball is to switch direction and move toward the concluding click, until the stopping condition occurs, when there is a click higher up the end line. This is clearly repetitive and needs a while loop. The status is only to exam the y coordinate of the mouse click against the the meridian of the stop line. The body of the loop is very brusque, since nosotros already take the utility function getShift , to figure out (dx, dy) values.
def moveInBox ( shape , stopHeight , xLow , xHigh , yLow , yHigh , win ): #NEW '''Shape bounces in win so its centre stays within the low and loftier x and y coordinates, and changes direction based on mouse clicks, terminating when there is a click in a higher place stopHeight.''' scale = 0.01 pt = shape . getCenter () # starts motionless while pt . getY () < stopHeight : ( dx , dy ) = getShift ( shape . getCenter (), pt ) pt = bounceInBox ( shape , dx * calibration , dy * scale , xLow , xHigh , yLow , yHigh , win ) The variable pt for the last mouse click needed to be initialized some fashion. I chose to make the value exist the aforementioned equally the initial position of the ball, so both dx and dy are initially 0, and the ball does not start in move. (Alternatives are in Random Start Exercise beneath.)
I occasionally detected a problems when using the program. The brawl would get stuck simply outside the boundary and stay at that place. The fact that it was slightly beyond the boundary was a inkling: For simplicity I had cheated, and allowed the ball to go but one animation stride beyond the intended purlieus. With the speed and minor stride size this works visually. The original code was sure to brand an reverse spring back inside at the side by side step.
After some thought, I noticed that the initial version of the bounce3.py code for bounceInBox broke that assumption. When the brawl was where a bounce-back is required, a mouse click could change (dx, dy) and mess up the bounciness. The thought for a fix is not to let the user change the direction in the moment when the ball needs to bounce back.
Neither of the original boundary-checking if statements, by itself, e'er determines if the brawl is in the region where it needs to reverse management. I dealt with this situation by introducing a Boolean variable isInside . It is initially set as Truthful , so either of the if statements can correct it to Fake. So, at the cease of the loop, isInside is used to make sure the ball is safely within the proper region when in that location is a check for a new mouse click and a possible user aligning to (dx, dy).
three.three.four.ane. Exercise Moving Undraw¶
** As discussed above at Where to carve up the loop, the basic loop logic works whether the poly.undraw() call is at the outset or end of the loop. Write a variation makePoly2.py that makes the lawmaking work the other way, with the poly.undraw() at the beginning of the loop. Practice not change or move whatsoever other statement in the loop. The new place to cutting the loop does affect the lawmaking before and later on the loop. In detail, the extra statement cartoon poly is non needed after the loop is completed. Make other changes to the surrounding lawmaking to brand this work. Hints: [four]
3.3.iv.ii. Make Path Exercise¶
** Write a program that is outwardly very similar to makePoly.py , and call information technology makePath.py , with a role pathHere . The merely outward divergence between polyHere and pathHere is that while the get-go creates a closed polygon, and returns it, and the new one creates a polygonal path, without the final point being automatically connected to the starting time point, and a listing of the lines in the path is returned. Internally the functions are quite different. The modify simplifies some things: no demand to undraw anything in the principal loop - but depict the latest segment each time going from the previous betoken to the only clicked point. At that place are complications however: You lot do demand deal specially with the get-go point. It has no previous signal to connect to. I advise you handle this before the primary loop: If the point is inside the rectangle, draw the point so it is a visible guide for the side by side indicate. Earlier returning, undraw this initial point. (The place on the screen will still be visible if an initial segment is drawn. If no more points were added, the screen is left bare, which is the way it should exist, and an empty list of lines should be returned.) You besides need to recall the previous point each fourth dimension through the main loop. I suggest you retrieve individually well-nigh what should happen if you stop the drawing when the outset, second or third indicate is outside the rectangle. As well test each of those cases afterward the programme is written.
In your main program, call the makePath function ii times. Use the listing of lines returned to loop through and change the color of all the lines in i path and the width of the lines in the other path. A portion of a sample paradigm from this plan is shown below.
3.iii.4.3. Random Get-go Practise¶
* (Optional) I chose to have the brawl start motionless, by making the initial value of pt (which determines the initial (dx, dy) ) be the middle of the ball. Write a variation startRandom.py so pt is randomly chosen. Too make the initial location of the ball be random. You tin re-create the function getRandomPoint from bounce1.py.
three.3.4.four. Mad Lib While Exercise¶
** Write a plan madlib4.py that modifies the getKeys method of madlib2.py to use a while loop. (This is not an blitheness program, but this section is where you take had the most experience with while loops!)
Hints: This is actually the near natural arroyo. I avoided while loops initially, when only for loops had been discussed. In the original approach, nonetheless, it is redundant to detect every case of '{' to count the number of repetitions then find them all once again when extracting the cue keys. A more than natural way to control the loop is a while loop stopping when there are no further occurrences of '{' to discover . This involves some farther adjustments. You must cut the loop in a dissimilar place (to cease afterward searching for '{' ). As discussed before, cutting a loop in a different identify may crave changes before and after the loop, likewise.
iii.iii.iv.5. Find Hole Game Exercise¶
** Write a graphical game program, findHole.py , "Find the Hole". The program should use a random number generator to decide a circular "hole", selecting a point and a mayhap the radius around that point. These decide the target and are not revealed to the player initially. The user is so prompted to click around on the screen to "find the hidden hole". Y'all should show the points the user has tried. In one case the user selects a point that is inside the chosen radius of the mystery point, the mystery circle should appear. There should be a message announcing how many steps it took, and the game should end.
Hint: you have already seen the code to determine the displacement (dx, dy) between two points: utilize the getShift role in bounce2.py . Once you take the displacement (dx, dy) betwixt the hidden middle and the latest mouse click, the distance between the points is (dx*dx + dy*dy)**0.5 , using the Pythagorean Theorem of geometry. If this distance is no more than the radius that you have chosen for the mystery circle, then the user has institute the circumvolve! Yous can use getShift every bit written, or modify it into a function getDistance that straight returns the distance betwixt 2 points.
Many elaborations on this game are possible! Have fun with it!
3.3.5. Fancier Animation Loop Logic (Optional)¶
The final variation is the instance program bounce4.py , which has the same outward beliefs equally bounce3.py, but it illustrates a different internal design decision. The bounce3.py version has two levels of while loop in 2 methods, moveInBox for mouse clicks and bounceInBox for billowy. The bounce4.py version puts all the lawmaking for irresolute direction inside the main animation loop in the erstwhile outer function, moveInBox . There are now three reasons to suit (dx, dy): billowy off the sides, bouncing off the elevation or bottom, or a mouse click. That is a simplification and unification of the logic in one sense. The complication now is that the logic for determining when to quit is cached deep within the if - else logic, not at the heading of the loop. The exam for mouse clicks is inside the while loop and further within another if argument. The examination of the mouse click may merely lead to a change in (dx, dy), or is a indicate to quit. Here is the revised code, with a discussion after of the return statement:
def moveInBox ( shape , stopHeight , xLow , xHigh , yLow , yHigh , win ): ''' Animate a shape moving toward whatsoever mouse click below stopHeight and bouncing when its heart reaches the low or loftier x or y coordinates. The animation stops when the mouse is clicked at stopHeight or above.''' scale = 0.01 delay = . 001 dx = 0 #NEW dx and dy are no longer parameters dy = 0 #NEW while True : #NEW exit loop at return argument center = shape . getCenter () ten = center . getX () y = eye . getY () isInside = Truthful if x < xLow or x > xHigh : dx = - dx isInside = Simulated if y < yLow or y > yHigh : dy = - dy isInside = Imitation if isInside : pt = win . checkMouse () if pt != None : #NEW dealing with mouse click now hither if pt . getY () < stopHeight : # switch management ( dx , dy ) = getShift ( middle , pt ) ( dx , dy ) = ( dx * calibration , dy * scale ) else : #NEW get out from depths of the loop return #NEW shape . move ( dx , dy ) time . slumber ( delay ) Recall that a return statement immediately terminates office execution. In this case the function returns no value, but a bare return is legal to force the leave. Since the testing is not done in the normal while condition, the while condition is set equally permanently Truthful . This is not the well-nigh mutual while loop pattern! It obscures the loop exit. The choice between the arroyo of bounce3.py and bounce4.py is a matter of gustation in the given situation.
| [1] | "while ___", "exercise ___ while", "repeat while", "repeat until", "equally long as ___, do", "keep doing ___ as long as" |
| [ii] | You will need a loop. You tin print/append most all the numbers in the loop. You are probable to omit 1 number with but this code, merely afterwards looking at what you produce, it is piece of cake to separately include the remaining number. In that location are several ways to practise this. |
| [3] | Recall the congenital-in len function! It applies to lists. |
| [iv] | The bones issue is like to the old version: the undraw is non always needed – at the beginning in this case. In this place it is not needed the first time through the loop. The two basic approaches considered for the previous version even so work here: make an actress compensating action outside the loop or break into cases inside the loop. Farther hint: It is legal to draw a polygon with an empty vertex list - zilch appears on the screen. |
Source: http://anh.cs.luc.edu/handsonPythonTutorial/whilestatements.html
0 Response to "If Else Statement Ask Question Again"
Postar um comentário