Chapter 3 : Loops, Repeats and Conditions
We are now starting to type in longer listings with more lines. To make them easier to read, all the listings from now on will include a space after each line number.
Some lines will have more than one space after the number - they are indented to show the start and finish of sections of the program such as loops which are explained in this section. Again, this is for clarity and to make the workings of the program easier to understand.
You don't have to type in these spaces, though it doesn't matter if you do. You can see them when you list the program by first typing:
The LISTO command is fully explained in Appendix 1.
Deciding IF to ExecuteThe program in Section 2 which added two numbers together kept repeating the same lines over and over again, doing the same thing every time.
Suppose, though, we wanted the program to do one thing if we typed in one number and a totally different thing if we typed in something else. We could use the IF keyword.
If you already have a program in your machine's memory, get rid of it by typing:
If you should change your mind, you can get it back, provided you haven't started to enter a new program, by typing:
Now type in the following:
Notice the use of the symbols '>', '<', '=' and '<>' between first% and second% in lines 30 to 60.
The first two lines show how INPUT can be used to print a line on the screen and enter a number into a variable at the same time. The program will print the line, then wait for you to type in the number. The comma, incidentally, causes a question mark to be printed at the end of the line. If you don't want a question mark, leave out the comma.
Conditions AttachedThe IF keyword causes conditional execution. Basic checks the part which follows the keyword to see if it's true. If it is, it carries out the instruction following THEN. Line 30, for example, means:
If the value of first% is greater than the value of second% then print 'The first number was higher'.
If the value of first% is less than the value of second% then print 'The second number was higher'.
If the value of first% is equal to the value of second% then print 'The numbers were equal' and give x% a value of 1.
If the value of first% is not equal to the value of second% then print 'The numbers were not equal' and give x% a value of 2.
If you want the program to do one thing if the part following TO is true and another thing if it isn't, you can use the ELSE keyword; for example lines 50 and 60 could be combined into one:
This line means:
If the values of first% and second% are equal then print 'The numbers were equal' and set the value of x% to 1. If they are not equal then print 'The numbers were not equal' and set the value of x% to 2.
IF ... THEN Covering Several LinesAlthough the presence of the THEN keyword makes the meaning of the line clearer, in most cases it's possible to leave it out, though you must include it if it's followed by a star command. Its principle use is in enabling you to do things like this:
In this case, the section which is only executed if the expression following IF is true can be made to extend over several lines. Because there is nothing following THEN on the first line, Basic only executes the next two lines if x% is greater than y%. If this is not the case, it looks ahead for either an ELSE or ENDIF keyword and continues from there. Of course, if x% is greater than y%, the lines down to ELSE will be executed and those between ELSE and ENDIF skipped.
You only need ELSE if there is some action to be carried out if x% is not greater than y%.
Using a structure of this sort allows you to conditionally execute more instructions than you could conveniently put on one line but there is a further advantage. The line before ENDIF contains another IF keyword. In this line, the program only prints 'Game Over' if x% is not greater than y% and lives% equals zero. It is possible to put more than one IF keyword on a line, but there is a risk of ambiguity where you have several IFs and ELSEs mixed up together.
True or False?Basic uses two numbers called TRUE and FALSE. If you were to type:
you would discover that the value of TRUE is minus one and the value of FALSE is zero. There is a reason for this which will become apparent later in this guide.
As we have just seen, the IF keyword causes conditional execution. What the program does depends on what it finds following IF. Basic works out whether or not this part of the line is true and assigns a value to the whole lot; TRUE if it is true and FALSE if it isn't. Whether it goes on to execute the bit following THEN or the bit following ELSE depends on whether the value is TRUE or FALSE.
Although this looks like a piece of bad programming which should produce an error message, Basic will simply work out the values of the expressions on either side of the equals sign, decide that they are equal and give you the answer -1 which, as we have seen, is the value of TRUE. Similarly, if you typed:
Basic would decide that 2 was not greater than 3 and print:
which is the value of FALSE.
In CASE ... OF TroubleBefore we leave the subject of IF ... THEN, look at the following program, though you need not bother to type it in:
In this fairly trivial program, we examine the value of x% and take various steps depending on whether it is 1, 2, 3 or 4, in this case simply printing out a message. This would certainly work, but it can mean several wasted program steps.
Suppose x% was 1. The program detects this in line 20 and goes on to print 'You typed one'. Having done this, it must then check for other values of x% in lines 30, 40 and 50 before reaching the next step in line 60. This is a complete waste of time because x% can only have one value and we've already found it in line 20. We really only want to execute one of the four PRINT statements in lines 20 to 50, then move directly to line 60.
What we need is a command which will check the value of x%, take appropriate action and then move straight on to the next part of the program. For this, we can use a CASE ... OF ... ENDCASE structure:
10 INPUT x% 20 CASE x% OF 30 WHEN 1:PRINT "You typed one" 40 WHEN 2:PRINT "You typed two" 50 WHEN 3:PRINT "You typed three" 60 WHEN 4:PRINT "You typed four" 70 OTHERWISE 80 PRINT "You didn't type one, two, three or four" 90 ENDCASE 100 PRINT "End of program"
Line 20 looks like a rather strange use of the English language. What it means is that we examine the value of x% and compare it in turn with the various numbers following the WHEN keywords in lines 30 to 60. If the program finds a match on a particular line, it executes the remainder of the line following the colon and proceeds straight to line 100 following the ENDCASE keyword, ignoring the lines in between.
We've added a bit to this program that wasn't in the previous example. If the program doesn't find a match for x% in any of the numbers following the WHEN keywords, it executes the line following the OTHERWISE keyword, line 80. You don't have to have an OTHERWISE keyword in a CASE ... OF structure. You only need it if there is something to be done if none of the conditions following the WHEN keywords is met.
You can use CASE ... OF ... ENDCASE to check various unrelated conditions and take action according to the first which is true like this:
In this situation, we are comparing TRUE with the various expressions following the WHEN keywords. This means that we will have found a match as soon as we come across an expression which is true. If x% is greater than y%, we print 'You won!' and proceed to the next part of the program. If not, we check to see if a% equals b% and print 'We drew!' if it does.
You could use this arrangement if you only ever wanted to take one of the various courses of action. As soon as the program finds a match, it does whatever is on the rest of the line, then stops looking and moves to the ENDCASE keyword.
Round and Round the Repeat LoopIn Section 2 we used a GOTO command to make a program repeat itself indefinitely.
Experienced programmers don't like using GOTO, as it can make the program more difficult to follow and also makes it dependent on its line numbers. A better way is like this:
When the program encounters the command REPEAT, it remembers where it was and continues executing the program until it gets to UNTIL. It then works out whether or not the bit that follows UNTIL is TRUE and jumps back to where REPEAT was if it isn't.
Clearly, FALSE can never be true, so the program always repeats itself until we either shut down the machine or press Esc.
We could easily make the program end when, for example, we enter two numbers which add up to 10 by changing the last line:
or, if you like:
which will end the program if the first number is greater than the second one. Have a go at modifying the program to see what you can produce.
Counting the LoopsQuite often, we want a program to do something a certain number of times. Say, for instance, that you wanted your machine to print 'Hello' 10 times. You could do it like this:
Line 40 is a short way of saying:
Its effect is to increase count% by 1. This happens every time our program goes round the loop, so each time we reach UNTIL the value of count% tells us how many times we have been round it. When it gets to 10, the program stops.
This program works perfectly well, but there is a shorter way of doing it, provided we want count% to increase by the same amount each time. Type NEW to get rid of the old program, then try this:
For obvious reasons, this is known as a FOR ... NEXT loop. The program first sets count% to 1, then follows the instructions until it comes to NEXT, then checks to see if count% has reached the value following the TO in line 10. If it hasn't, it increases it by 1 and goes back to FOR to follow the loop again.
Once count% reaches 10, the program stops going round the loop and continues, or in this case ends.
Further Use of the Counting NumberYou can either use the variable count% to simply count how many times the program goes round the loop, or you can make use of it in other ways, like this for example:
This example shows us that the thing which governs how many times we go round the loop doesn't have to be a simple number, but could be a variable. In this case, we enter a number ourselves to tell the program how many times to go round the loop.
If you were to leave out the semi-colon (;) in line 30, the program would print a substantial gap between the word 'number' and the number following it, like this:
The reason for this is that Basic usually allows room for 10 characters on the screen when printing a number unless we tell it not to. The string inside the quotes ends with a single space between the word 'number' and the quote symbol, and the first nine lines of the loop each contain a further nine spaces before the number.
This is fine if we want the right-hand digits of the numbers to line up - you can see that the '0' of the '10' in the last line is underneath the other numbers. Sometimes, though, we don't want this, so we include the semi-colon, which has the effect of pushing the number as far as it will go to the left. This makes the screen look like this:
Your counting number doesn't necessarily have to increase by 1 each time. Try this, for example:
The use of STEP followed by 2 makes this program print even numbers from 2 to 10. You can even make it count backwards by using a negative number following STEP:
Notice the way that 10 comes before 2 in this example - we must always put the initial value of count% first and the final value last.
Waiting Around Sometimes we may wish to make the program wait a certain length of time before doing something. This is particularly useful in games programs. We could do it easily by making it count up to some large number, for example:
The snag with this technique is that you can never be sure how long it will take. This line will take something like 14 seconds on an older machine fitted with an ARM2 processor; if you have an A3010, A3020 or A4000, its processor will be an ARM250, which is a bit faster, and a machine with an ARM3, such as an A5000, A540 or an upgraded A310 or A3000 will be faster still. A Risc PC with a StrongARM processor would take hardly any time at all.
Fortunately RISC OS provides us with an accurate means of measuring time. Your machine has a counter which is increased once every hundredth of a second and you can read it by using the Basic variable TIME. This should not be confused with the date and time of day, which you can also read with the variable TIME$.
Try this in immediate mode:
This simple program sets t% to the current value of TIME and keeps repeating its empty loop until TIME exceeds this number by at least 500.
When you press Return, you will have to wait five seconds for the Basic prompt to reappear. This is because TIME is in centi-seconds or hundredths of a second.
You will notice that we used a 'greater than' symbol rather than an equals sign. This is a safeguard, in case our program didn't happen to read the value of TIME when it was exactly 500 greater than t%. This is not very likely in this program, as our simple loop will take much less than one hundredth of a second to run, but it could happen in a more complicated program with a longer loop. If it did, we would find that our loop would go on repeating long after it should have stopped.
WHILE ... ENDWHILEThere's one more type of loop, a bit like the REPEAT ... UNTIL loop but with one major difference. It looks like this:
In this loop, we print the value of x% and reduce it by 1 each time we go round the loop.
We could do something like this with a REPEAT ... UNTIL loop, of course, but there's one big difference. A REPEAT ... UNTIL loop checks the condition that makes the loop repeat at the end of the loop; a WHILE ... ENDWHILE loop checks it at the beginning. You may think this doesn't make much difference, but consider what would happen if x% was already 2 or less before we reached the loop. In this situation, we may not want our program to print anything at all. A REPEAT ... UNTIL loop must always be executed at least once but a WHILE ... ENDWHILE loop needn't be run at all.
We've seen in this section how listings may be improved by leaving a space after the line number and indenting. This means that two extra spaces are added during multiple line IF ... THEN structures, CASE ... OF ... ENDCASE structures and FOR ... NEXT, REPEAT ... UNTIL and WHILE ... ENDWHILE loops. These spaces and indentations have no effect on the way the program works and you may prefer to leave them out to save typing. As we saw at the beginning of the section, you can list the program with spaces and indentations by using the LISTO command.