This is the fourth article of a nine part series that teaches VB.NET via the development of a text-based game. The last article discussed variables, conditionals, and Console input. This article will commence the discussion of loops, starting with the While loop and the Do loop. Join us as we continue on our journey.
So far, we know how to write information to the console, read information from the console, and work with conditionals. Before we can get started though, we're missing one key concept: loops. Obviously, a game involves repeating a set of instructions over and over again until the user quits. This repetition is, of course, made possible through loops. Visual Basic has four loops, each designed with a particular use in mind. They are the While loop (While ...End), the Do loop (Do ...Loop), the For loop (For ...Next), and the For Each loop (For Each ...Next). We'll cover them all here in the order that I've listed them.
While...End
The first loop is the While loop, and it's probably the most basic loop available. It loops over a set of instructions as long as a given condition comes out True. This loop will be particularly useful in our game because we simply need to follow a regular pattern of accepting user input, acting on that input, accepting more input, acting on the new input, etc. This pattern is repeated any number of times until the user quits the game.
One of the simplest loops we can create is one that runs forever without terminating—in other words, an infinite loop. Let's create a loop that accepts user input, echoes the input to the user, and then repeats the process over and over again:
Dim input AsString
WhileTrue
input = Console.ReadLine()
Console.WriteLine(input)
EndWhile
(Note: in Visual Studio, you can force the program to exit by pressing the “Stop Debugging” button or by pressing Control+Alt+Break. This is particularly useful in cases where the program gets stuck in a loop, as in the above example.)
Notice how the expression is simply True. Since this condition is, obviously, True , then the loop will continue forever (in theory, that is), accepting user input and then echoing the input. Of course, this behavior is seldom what we want in a loop. We want the loop to terminate at some point. There are two ways of doing this. The first is to manually break out of the loop using the Exit statement, which will immediately transfer control to the first statement outside of the loop. Let's stick an Exit statement in our loop:
Dim input AsString
WhileTrue
input = Console.ReadLine()
Console.WriteLine(input)
ExitWhile
EndWhile
Notice how we must specify exactly what we're exiting out of. This way, we can exit out of multiple layers of loops, and we can even exit out of the subroutine entirely (Exit Sub).
The code in the previous section will accept user input, echo the input, and then stop as soon as it encounters the Exit statement. Typically, though, we'll want to attach some sort of condition to our Exit statement (otherwise, why use a loop?). For example, we can choose to exit the loop only if the user types “quit”:
Dim input AsString
WhileTrue
input = Console.ReadLine()
Console.WriteLine(input)
If input.ToLower() = "quit"Then
ExitWhile
EndIf
EndWhile
If the user types “quit,” then we exit. We convert the input to lower case in order to get around case sensitivity. That way, the user can type “QUIT,” “QuIt,” etc., and the effect will be the same. In any case, the above code is bad. We evaluate an expression inside of the loop and then exit depending on the result. So, in effect, we're ignoring the basic functionality provided for us by the loop. Let's rewrite our loop to make it better (and shorter in code length) by incorporating the condition into the loop itself:
Dim input AsString= ""
While input.ToLower() <> "quit"
input = Console.ReadLine()
Console.WriteLine(input)
EndWhile
As you can see, we've replaced True with a more complex expression. In fact, this expression is the opposite of the expression we previously used in our If statement. Instead of checking to see if the user has typed “quit,” we check to see if the user has not typed quit. If the user hasn't, then we run the loop. The combination of less-than and greater-than symbols (<>) in the expression is actually the “not equal to” operator. Although it wouldn't be as elegant (and, indeed, I'm just pointing it out here to introduce a new operator without going too much off course), we could have instead added the Notoperator to negate the earlier expression:
WhileNotinput.ToLower() = "quit"
Also, be sure to note that we assign a value to inputbefore we run the loop. This is because we can't run the next line's comparison using an unassigned variable. The code will compile, but the compiler will generate a warning, and an exception will be thrown at runtime.
The Do ...Loop statement offers another loop that we can use, the Do loop. It's similar to While ...End , but it's more complex, supporting a variety of behaviors. In its most basic form, it's not any different from an infinite While loop, except we're able to omit the expression altogether. Here's a new version of our input-echoing loop, rewritten using Do ...Loop:
Dim input AsString
Do
input = Console.ReadLine()
Console.WriteLine(input)
Loop
If we want to terminate the loop, we have to do so manually by using Exit, as we did earlier with the infinite While loop, since we didn't provide an expression. However, we must specify that we're exiting a Do loop instead of a While loop. Here, we exit if the user types “quit”:
Dim input AsString
Do
input = Console.ReadLine()
Console.WriteLine(input)
If input.ToLower() = "quit"Then
ExitDo
EndIf
Loop
The real value in the Doloop, however, lies in its support for multiple behaviors. The loop supports two basic modes of behavior: Whileand Until. We can either tell our loop to run while a condition is true, or we can tell our loop to do something until a condition is true. Let's take these two behaviors one at a time, starting with the While behavior. Let's create a loop that will echo user input as long as (while) the user does not type “quit”:
Dim input AsString= ""
DoWhileinput.ToLower() <> "quit"
input = Console.ReadLine()
Console.WriteLine(input)
Loop
As before, we must assign a value to input. Actually, as you've probably noticed, the above loop bears a strong resemblance to our earlier While loop. Hold that thought for just a moment while we move on to the second mode of behavior, Until. Let's recreate our loop to echo user input until the user types “quit”:
Dim input AsString= ""
DoUntilinput.ToLower() = "quit"
input = Console.ReadLine()
Console.WriteLine(input)
Loop
Though the above two loops function the exact same way, the expressions used are opposites. In effect, Do Until operates while the expression comes out False . Then, when it comes out True, the loop terminates. Sometimes, this mode of behavior is more straightforward and readable. In fact, it suits our example quite well.
Earlier, I pointed out the DoWhileexample and the Whileexample looked and performed very similarly. Actually, though, there's one important difference: the Doloop can test the expression after the loop's instructions are run. Consider, for example, the following While loop:
WhileFalse
Console.WriteLine("Hello.")
EndWhile
Since the expression is False, the call to WriteLine within the loop will never actually be executed. Execution will essentially skip right over the loop. Sometimes, this is appropriate behavior since we may never want a loop to run if the expression comes out False in the beginning. However, there are situations where we want the loop to run at least once, and the While loop is not fitted to these situations. This can all be fixed if, instead of checking the expression before each iteration, we check the expression after each iteration. To enable this behavior in a Do loop, we simply need to specify the expression after Loop rather than after Do. The following loop, for example, will execute exactly once, even though the expression is False:
Do
Console.WriteLine("Hello.")
LoopWhileFalse
We can make use of this behavior with our previous example, too. Before, we had to assign a blank string to input because its value was checked before the user was able to actually input anything. We can eliminate the need for this assignment, however, by checking the expression after the loop iterates. At this point, the user will have entered something and the variable will have been assigned a value:
' No assignment:
Dim input AsString
Do
input = Console.ReadLine()
Console.WriteLine(input)
LoopWhileinput.ToLower() <> "quit"
This behavior also works with Until :
Dim input AsString
Do
input = Console.ReadLine()
Console.WriteLine(input)
LoopUntilinput.ToLower() = "quit"
This behavior models the behavior of the generic do loop in other languages, so it's the behavior with which most programmers will be familiar. As you've seen, though, the Visual Basic version of the loop is more flexible. However, a Do loop should not be used in situations where a simple While loop will suffice.