6.2 While - Loop
While-Loop
De while loop is eigenlijk eenvoudiger uit te leggen. Hij kent één vergelijking, de lus-voorwaarde en zolang die true is blijft de loop doorlopen.
$i=0;
while($i<10){
$i++;
...
}
Met deze while-loop doe je eigenlijk hetzelfde als in de for loop: for($i=0; $i<10; $i++)
Je ziet dat de startwaarde op regel 1 staat en de lus-teller op regel 3.
Deze loop is iets 'gevaarlijker', omdat de drie fases van de loop niet per sé bij elkaar staan. Dat is 'gevaarlijk', omdat je dan eerder het overzicht verliest en misschien het ophogen met de lus-teller (in het voorbeeld regel 3) vergeet. Ook kan het minder overzichtelijk zijn.
Bij een while-loop moet je net als bij een for-loop altijd nadenken over de 3 fasen:
- Wat is de start-waarde; hoe begint de loop (in het voorbeeld $i=0)?
- Wat is de lus-teller?
- Wat is de lus-voorwaarde??
Stel je hebt een functie die een row uit de database haalt, deze functie heet getRow() en deze functie returned de row uit de database. Als er geen rows meer zijn dat wordt er 0 teruggegeven. Je kunt nu een while-loop gebruiken om alle regels af te drukken:
<?php
$dezeRegel = getRow();
while($dezeRegel<>0){
echo $dezeRegel;
$dezeRegel=getRow();
}
?>
Het is gebruikelijk om dit op deze manier uit te voeren, maar het kan ook in een for-loop. Welke methode vind jij beter leesbaar?
<?php
for( $dezeRegel = getRow(); $dezeRegel<>0; $dezeRegel=getRow();){
echo $dezeRegel;
}
?>
In sommige gevallen wil je eindeloze loop maken. Een while loop kun je eenvoudig eindeloos maken: while(true){...
Do-While
De do-while loop is een variant op de while-loop. In deze loop staat de lus-voorwaarde aan het eind in plaats van in het begin zoals bij de while-loop en de for-loop.
<?php
$i = 0;
do {
echo $i;
} while ($i > 0);
?>
Wat denk je dat deze code doet? Probeer deze code. Als je deze code uitvoert, dan zie je dat de loop 1x uitgevoerd wordt en dat terwijl $i nooit groter dan 0 is (en dus de vergelijking nooit true oplevert). Een Do-While loop wordt dus altijd minimaal 1x uitgevoerd. Dat geldt niet voor de 'gewone' while-loop of voor de for-loop.
Stroomdiagrammen
Hieronder zie je twee stroom-diagrammen. Welke hoort bij de while en welke bij de do-while? Welke zou het beste passen bij een for-loop?
Break
Met een break statement spring je uit de huidige loop. Je gaat direct naar het eind en begint met het statement dat vlak na de } staat aan het einde van de loop. De lus-code wordt dus niet verder uitgevoerd.
Continue
Met het continue statement stop je met de huidige iteratie en ga je naar het begin van de loop om de volgende iteratie te beginnen. De lus-code wordt dus weer vanaf het begin uitgevoerd. Bij een for-loop wordt dat we de lus-teller bijgewerkt en wordt gekeken of er nog aan de lus-voorwaarde wordt voldaan.
Opdracht 1
De volgende code moet alle getallen van 1 t/m 25 afdrukken, maar de programmeur heeft één regel code vergeten. Kun jij deze regel toevoegen, zodat de getallen 1 t/m 25 worden afgedrukt?
<?php
$count=0;
while (true) {
echo $count . "<br>";
if ( $count == 25 ) {
break;
}
}
?>
Opdracht 2a
Met de volgende code gooi je met twee dobbelstenen ($dice1 en $dice2). Beide dobbelstenen krijgen een willekeurige waarde van 1 t/m 6, net als een dobbelsteen.
$dice1=rand(1,6);
$dice2=rand(1,6);
echo $dice1. "-" .$dice2;
echo "<br>";
Zet de code in een loop, zodat er 10x met beide dobbelstenen wordt gegooid.
De output ziet er bijvoorbeeld als volgt uit:
1-2
5-6
4-2
5-3
4-3
3-1
5-6
6-1
3-2
1-3
Verander de loop nu, zodat de code net zolang blijft 'gooien' totdat er twee maal 6 is gegooid. Op de laatste regel moet dus 6-6 komen te staan.
Tenslotte, zet een getal voor de worp, zodat je eenvoudig kan zien hoe vaak de code de dobbelstenen heeft 'gegooid'. Zet ook achter elke worp de som van de twee dobbelstenen. De output ziet er dan bijvoorbeeld als volgt uit.
worp 1: 1-2 totaal 3
worp 2: 5-6 totaal 11
worp 3: 4-2 totaal 6
worp 4: 5-3 totaal 8
worp 5: 4-3 totaal 7
worp 6 :3-1 totaal 4
worp 7: 6-6 totaal 12
Opdracht 2b
Pas de code van opdracht 2a aan, zodat je met drie dobbelstenen gooit. De output iet er bijvoorbeeld als volgt uit:
worp 1: 3-4-3
worp 2: 1-1-6
worp 3: 2-2-5
worp 4: 3-2-3
...
'Gooi' nu net zolang met de drie dobbelstenen totdat je drie maal een 6 heb gegooid.
Opdracht 3 - Simulatie - extra punten
In opdracht 2b gooi je bet zo lang met 3 dobbelstenen totdat je drie maal een 6 heb gegooid. Hoe groot is nu de kans om 3x een 6 te gooien? Vanuit de wiskunde kun je dit berekenen, maar als programmeur kun je dit ook bepalen met een simulatie.
We gaan nu via een simulatie bepalen wat de kans is om 3x6 te gooien. Omdat te doen gaan we 1000 keer net zolang gooien totdat we 3x6 hebben gegooid. We hebben dan 1000 uitkomsten. Elke uitkomst geeft aan hoe lang het duurde om 3 x 6 te gooien.
Om dit probleem aan te pakken delen we het op in kleine stapjes.
Functies
We gaan gebruik maken van functies.
Functies werken hetzelfde als in andere talen en in de JavaScript lessen hebben we het hier over gehad. Functies hebben we nog niet gehad in PHP, maar in het volgende filmpje wordt uitgelegd hoe wat een functie ook alweer is en hoe je die in PHP moet gebruiken: Uitleg over functions.
Stap 1 - maak functie throwDice($numberOfDice)
Maak een functie die je aanroept met throwDice($numberOfDice)
De functie krijgt het aantal dobbelstenen mee dat moet worden gegooid en de functie returned het totaal aantal ogen dat je hebt gegooid.
Stap 2 - voer de functie net zolang uit totdat de uitkomst 18 is
Drie maal zes geeft een uitkomst van 18. Voer de functie dus net zolang uit totdat de uitkomst 18 is. Tel hoeveel keer je de functie hebt aangeroepen.
Maak ook hiervan een functie. Noem de functie waitForResult($result)
. De functie krijgt nu 18 mee als parameter en returned hoe vaak het heeft moeten 'gooien' om tot het resultaat te komen. Vanuit deze functie waitForResult
roepen we dus de functie throwDice
aan.
Dus bijvoorbeeld:
Je roept waitForResult(18) aan en je krijgt 101 terug. Dat betekent dat de computer 101 x heeft gegooid en dat er toen pas 18 was gegooid.
Of je roeptwaitForResult(7) en je krijgt 12 terug. Dat betekent dat de computer 12 keer heeft gegooid en dat er toen 7 was gegooid.
Stap 3 - voer de simulatie tig-keer uit.
In stap 2 voeren we de simulatie één keer uit. We wachten één keer op een bepaalde uitkomst bij het werpen van de dobbelstenen.
De uitkomst hangt af van geluk. Het kan zijn dat we gelijk in één keer 18 gooien, maar het kan ook meer dan 100 worden duren. Als we nu heel vaak gooien en het gemiddelde berekenen dan filteren we de geluksfactor er een beetje uit. We gaan in deze stap dan ook 1000x de functie waitForResult(18) uitvoeren en bepalen het gemiddelde van de return waarde van deze functie.
De functie geeft terug hoeveel worpen het kostte om 18 te gooien. Als we dat 1000 keer doen en we bepalen het gemiddelde van al deze aantal worpen dan weten we hoelang je gemiddeld moet wachten op een uitkomst van 18 als je met drie dobbelstenen gooit.
Stap 4 - nog een stapje verder
En wat is het antwoord? Met je huidige simulatieprogramma kun je ook heel eenvoudig bepalen hoe lang het duurt om bijvoorbeeld 11 te gooien of 10, of 9,....
Kun je van alle mogelijke uitkomsten 3 tot en met 18 nu in een loop bepalen hoe lang het gemiddeld duurt om dit aantal ogen met drie dobbelstenen te gooien?
--