|
Sometimes, you don't know at the start exactly how many times you want to loop, so instead, you want to continue looping until a specific condition is met.
Say you need to walk up some stairs. You don't count the stairs before you start – you just keep walking until you get to the top. So instead of:
numberOfStairs = CountTheStairs() For n = 1 To numberOfStairs Walk_up_a_stair Next n
you might say:
Do Walk_up_a_stair Loop Until you_reach_the_top
Let's see how to do this in code.
In Chapter 2, we wrote the Snake Eyes dice game. It was quite a good game, except for one problem – it was a bit boring and repetitive to play!
Don't worry, though. Whenever there's something boring and repetitive to do, you can usually get a computer to do it. Let's write a program now that will play a whole game of Snake Eyes for us. We won't be looking at the pretty version of the game we made in the previous two chapters but we'll be looking at a stripped-down version, where the concept of snake eyes is still apparent, even if the visual appearance is different.
Create a new ASP.NET page called DoUntil.aspx. Add a Button control, then a blank line, and then a Label. Clear the label's Text property to blank, and the change the button's Text property to Play the whole game.
Now double-click the Button, and modify the handler so that it looks like the following:
Sub Button1_Click(sender As Object, e As EventArgs) Label1.Text = "" Dim dice1, dice2, score As Integer Do dice1 = Int(Rnd() * 6) + 1 dice2 = Int(Rnd() * 6) + 1 score = score + (dice1 + dice2) Label1.Text = Label1.Text & "Rolled a " & dice1 & _ " and a " & dice2 & "<br/>" Loop Until dice1 = 1 And dice2 = 1 score = score - 2 Label1.Text = "You lost! Your total score would have been " & _ score.ToString() & "<br/><br/>" & Label1.Text End Sub
Done! Now press F5 to run the page. When you click the Button, you'll get your score displayed, along with a log of every roll:
There's nothing really complicated here. Let's run through it line by line. First of all, we just make sure there isn't anything in the label from the last time the procedure ran. You have already seen this line from earlier in the chapter:
Label1.Text = ""
Next we declare some variables of type Integer – don't worry about this for now, we'll cover it properly in the next chapter. Just remember that we now have three numbers, dice1, dice2, and score:
Dim dice1, dice2, score As Integer
Now we come to the loop itself. Every time the loop runs, we want to roll both dice, add that to our score, and then append the dice values to the end of the label:
Do dice1 = Int(Rnd() * 6) + 1 dice2 = Int(Rnd() * 6) + 1 score = score + (dice1 + dice2) Label1.Text = Label1.Text & "Rolled a " & dice1 & _ " and a " & dice2 & "<br/>" Loop Until dice1 = 1 And dice2 = 1
We keep on doing it until our condition is reached, in other words, until both dice have a value of one.
If the player rolls two ones, we shouldn't add that to the score, but in the loop above we always add the values, so when the loop finishes, the score will be 2 higher than it should be. We simply take that away, and then put a summary of the game at the very beginning of the label:
Label1.Text = "You lost! Your total score would have been " & _ score.ToString() & "<br/><br/>" & Label1.Text
You can see that we don't know at the start of the game how many times this loop will run – we just keep going until a particular condition is met. (In theory, this particular example could run forever – the computer/player would need to be very lucky though!)
In the example above, the computer keeps going until something suddenly becomes true – the case where both dice throw a one. Sometimes, you want a similar loop, but instead of looping until something becomes true, you want to loop while something is true. In this case, you just use While instead of Until.
It is usually possible to re-phrase Until conditions so that they will work in a While loop. For example, our loop above could be:
Do dice1 = Int(Rnd() * 6) + 1 dice2 = Int(Rnd() * 6) + 1 score = score + (dice1 + dice2) Label1.Text = Label1.Text & "Rolled a " & dice1 & _ " and a " & dice2 & "<br/>" Loop While dice1 <> 1 Or dice2 <> 1
but this is much harder to understand. You're saying "carry on while either one of the dice isn't 1". It's just far easier to say "carry on until both of them are 1".
There will be other circumstances where While is the clearer choice. You can choose whether to use Until or While – pick the one that you find easiest for the particular condition you're testing.
If you put the While or Until condition at the end of the loop, then the loop will always execute at least once, even if the condition is definitely false. For example, this will run once:
Do ' This code will run once Loop While 1=2
In our examples, we couldn't test the dice until we had rolled them – and the roll was inside the loop. However, sometimes we want to do the test before running for the first time. It's easy to do – you need to just move the condition statement:
Do While 1=2 ' This code will not run at all Loop
Sometimes, you'll want to get out of a loop before it's really finished. This often happens when you have an If statement inside a loop, and you find that really, there's no point in carrying on.
To exit a For loop, just type:
Exit For
Similarly for a Do loop:
Exit Do
You shouldn't need to do this too often, but occasionally it's a useful trick. For example, we might not want to let the computer's score get too high:
Do dice1 = Int(Rnd() * 6) + 1 dice2 = Int(Rnd() * 6) + 1 If (score + dice1 + dice2) > 700 Then Exit Do End If score = score + (dice1 + dice2) Label1.Text = Label1.Text & "Rolled a " & dice1 & _ " and a " & dice2 & "<br/>" Loop Until dice1 = 1 And dice2 = 1
|