Leereenheid 2
Programmeren met herhaling en keuze
Inhoud hoofdstuk 2
Programmeren met herhaling en keuze Introductie Leerkern 1 2
3
4
5 6
Algoritmen Variabelen en toekenning 2.1 Variabelen en waarden 2.2 Toekenningen en uitdrukkingen 2.3 Variabelen in JavaLogo Herhalingsopdrachten 3.1 Voorbeeld van een herhaling 3.2 Algemene vorm van de herhalingsopdracht 3.3 Een toepassing Keuzeopdrachten 4.1 Twee voorbeelden 4.2 Algemene vormen van de keuzeopdracht 4.3 Een toepassing Animatie Drie uitdagende programma’s
1
Starten met programmeren
Hoofdstuk 2
Programmeren met herhaling en keuze
INTRODUCTIE
In het vorige hoofdstuk hebben we geleerd hoe we vanuit een JavaLogoprogramma een pen kunnen besturen om daarmee gekleurde lijnen en vlakken te kunnen tekenen. Eerst werden alle tekenopdrachten in een methode tekenprogramma() geplaatst; daarna leerden we u om extra methoden toe te voegen en die ook te gebruiken. Alle methoden die we schreven, bestonden uit een enkele rij opdrachten. Voor sommige methoden leidde dat tot veel herhaling. Een twintighoek met zijde 50 zouden we bijvoorbeeld alleen kunnen tekenen door twintig maal de opdrachten pen.vooruit(50); pen.rechts(18); te herhalen. Dat moet beter kunnen. In dit hoofdstuk leren we hoe we methoden kunnen structureren, bijvoorbeeld door aan te geven dat een bepaalde opdracht of reeks opdrachten een aantal keren herhaald moet worden. We zullen daarbij eerst wat afstand nemen van JavaLogo en zelfs van programmeren. Al voor er computers bestonden, werden er rekenvoorschriften ontworpen om bepaalde problemen op te lossen. Een voorbeeld: in de zestiende eeuw bedachten de geleerden Lilius en Clavius een methode om voor een willekeurig jaar uit te rekenen op welke datum Pasen valt in dat jaar. Dergelijke rekenvoorschriften noemen we ook wel algoritmen. In paragraaf 1 gaan we in algemene zin naar algoritmen kijken. In de volgende paragrafen leren we de belangrijkste elementen kennen waaruit we een algoritme op kunnen bouwen, en passen we die ook toe in JavaLogo-programma’s: elke methode is een uitwerking van een (klein) algoritme. In paragraaf 5 bekijken we hoe we in JavaLogo eenvoudige animaties kunnen maken, waarbij de vaardigheden uit de rest van het hoofdstuk goed van pas zullen blijken te komen. Ook dit hoofdstuk heeft tot slot een bijlage, waarin we u leren hoe u JavaLogo-programma’s op het web kunt plaatsen.
LEERKERN 1
Algoritmen
Hoe bereidt men het toetje tiramisu? Hoe breit men een kabeltrui voor een zevenjarige? Hoe telt men een rij getallen bij elkaar op? Hoe vindt men alle priemgetallen (getallen die alleen deelbaar zijn door 1 en zichzelf, zoals 2, 3, 13 en 83) onder 1 000 000? Hoe bepaalt men de kortste weg tussen twee steden? Hoe rekent men uit op welke dag 29 juli 2488 zal vallen?
2
Leereenheid 2
Algoritme
Programmeren met herhaling en keuze
Al deze vragen hebben gemeen, dat hun antwoord een voorschrift is, een stappenplan dat aangeeft hoe u het gewenste resultaat kunt bereiken. Een dergelijk stappenplan, in de vorm van een reeks uitvoerbare opdrachten, noemen we ook wel een algoritme. Hoewel recepten en breipatronen ook algoritmen zijn, wordt de term vooral gebruikt voor rekenkundige voorschriften. De gegeven voorbeelden maken ook duidelijk dat er al algoritmen bedacht werden lang voor er computers bestonden. In de introductie noemden we al de methode voor de bepaling van de paasdatum van Lilius en Clavius. Een nog veel ouder voorbeeld is de handige methode om priemgetallen te vinden die de Griek Erathostenes bedacht in de derde eeuw voor Christus. Deze methode draagt nog steeds zijn naam: hij staat bekend als de zeef van Erathostenes. Wij gaan op deze algoritmen overigens verder niet in. Het woord algoritme is afgeleid van de naam van een Arabische schrijver van leerboeken: Abu Ja’far Mohammed ibn Mûsâ al-Khowârizmî, die leefde omstreeks 825. De naam betekent: vader van Ja’for, Mohammed, zoon van Mozes, geboren in Khowârizm. Het woord algoritme is gevormd uit het laatste gedeelte van de naam: al-Khowârizmî. AlKhowârizmî schreef een beroemd boek Kitab al jabr w’ahl. Van deze titel stamt een ander woord af dat we kennen in onze taal, namelijk algebra (‘al jabr’).
Bij het programmeren hebben we ook te maken met algoritmen. Stel bijvoorbeeld dat u met behulp van JavaLogo de vlakvulling zou willen tekenen uit figuur 2.1. U moet dan een voorschrift bedenken dat de pen op de juiste manier bestuurt, en liefst een handig voorschrift, zodat niet elke penbeweging afzonderlijk hoeft te worden opgeschreven.
FIGUUR 2.1
Basisopdrachten en combinatiemogelijkheden
Vlakvulling van driehoeken in drie kleuren
Een algoritme is opgebouwd uit twee ingrediënten. Ten eerste is er een aantal basisopdrachten. De persoon of machine die het algoritme uitvoert, moet die basisopdrachten beheersen. Bij recepten zijn dat opdrachten als fruit de uitjes, schil de aardappels of voeg peper naar smaak toe. In breipatronen gaat dat bijvoorbeeld om het opzetten van steken en het breien van steken recht of averecht. Ten tweede zijn er manieren om die basisopdrachten te combineren. Bij recepten is dat meestal alleen opeenvolging: er staat een aantal basisopdrachten achter elkaar. Bij programmeren en breien is naast opeenvolging in elk geval ook herhaling van belang (brei 17 pennen 1r 1a, of teken 20 keer een rij driehoeken).
3
Starten met programmeren
OPGAVE 2.1
a Van welke basisopdrachten hebt u gebruikgemaakt bij het besturen van de pen in JavaLogo? (Houd bij de beantwoording van deze opgave even geen rekening met eigen, extra methoden.) b Op welke manier zijn die basisopdrachten tot nu toe gecombineerd? OPGAVE 2.2
Probeer voor een persoon die twee getallen bij elkaar op kan tellen, een voorschrift te formuleren voor het optellen van een willekeurige rij getallen. (NB: de persoon kan dus niets anders dan twee getallen optellen.) De basisopdrachten van JavaLogo genoemd in de uitwerking van opgave 2.1, zijn uniek voor die taal. In paragraaf 2 van dit hoofdstuk besteden we aandacht aan één extra basisopdracht, die in zeer veel hogere programmeertalen voorkomt, namelijk de toekenning, ofwel de mogelijkheid om een bepaalde waarde onder een bepaalde naam te onthouden.
Toekenning
Voorbeeld
De eerste opdracht in het algoritme van Lilius en Clavius voor het berekenen van de paasdatum, kunnen we in woorden als volgt opschrijven: ‘Deel het jaar waarvoor de datum berekend moet worden, door 19, tel bij de rest van die deling 1 op en noem het resultaat A.’ Voor het jaar 1905 bijvoorbeeld levert dit 5 + 1 = 6 op (bij deling van 1905 door 19 blijft een rest van 5 over). Meer wiskundig kunnen we dit opschrijven als A = rest(jaar/19) + 1 We onthouden de rest van de deling jaar/19 vermeerderd met één onder de naam A, ofwel: we kennen die waarde toe aan de variabele A. In paragraaf 2 gaan we nader in op variabelen en toekenningen. Er zijn verder drie standaardmanieren om basisopdrachten te combineren: opeenvolging, herhaling en keuze. Deze drie komen in de een of andere vorm in alle hogere programmeertalen voor.
Opeenvolging
Opeenvolging is de mogelijkheid een aantal opdrachten na elkaar uit te voeren. We hebben deze mogelijkheid al toegepast in het vorige hoofdstuk.
Herhaling
Herhaling is de mogelijkheid om een opdracht of een reeks opdrachten te herhalen tot aan een bepaalde voorwaarde is voldaan. Het algoritme voor het optellen van een rij getallen uit opgave 2.2 bevat een herhaling; het schrijft voor om een opdracht te herhalen tot we alle getallen gehad hebben. In paragraaf 3 bekijken we herhaling in JavaLogo.
Keuze
De derde is keuze, de mogelijkheid om de uitvoering van een bepaalde opdracht afhankelijk te maken van een voorwaarde. Een voorbeeld kunnen we ontlenen aan de berekening van de paasdatum. Stel, op een gegeven moment hebben we uitgerekend hoeveel dagen na 21 maart het Pasen is; dit getal hebben we onthouden onder de naam P. Is P bijvoorbeeld gelijk aan 3, dan valt Pasen dat jaar op 24 maart; is P 17, dan valt Pasen op 7 april. Om uit P de paasdatum te berekenen, moeten we
4
Leereenheid 2
Programmeren met herhaling en keuze
twee gevallen onderscheiden: als P 10 of kleiner is, valt Pasen op (21 + P) maart; is P groter dan 10, dan valt Pasen op (P – 10) april. In een algoritme zouden we dat bijvoorbeeld als volgt opschrijven: ALS (P ≤ 10) DAN paasdatum = P + 21 maart ANDERS paasdatum = P – 10 april
In paragraaf 4 gaan we nader in op keuze in JavaLogo. 2
Variabelen en toekenning
In deze paragraaf behandelen we een onderwerp waarvan het belang pas in de paragrafen daarna volledig duidelijk zal worden. Het gaat om de manier waarop een programma gebruik kan maken van de geheugenfunctie van een computer, door waarden onder een bepaalde naam op te slaan. We kijken naar het begrip variabele, naar toekenningen aan variabelen en tot slot naar het gebruik van variabelen in JavaLogo. 2.1
Variabele
VARIABELEN EN WAARDEN
We kunnen een variabele opvatten als een hokje in het computergeheugen, waar een bepaalde waarde (een string zoals "rood", of een getal zoals 17.5) in onthouden kan worden en dat aangeduid wordt met een bepaalde naam. Wat abstracter kunnen we ook zeggen dat een variabele een combinatie van een naam en een bijbehorende waarde is. Tabel 2.1 toont drie variabelen: een variabele kleur met waarde "rood", een variabele zijde met waarde 100 en een variabele stap met waarde 17.5. Variabelen en waarden
TABEL 2.1 naam
waarde
kleur zijde stap
"rood" 100 17.5
De waarde van een variabele kan tijdens de uitvoering van een programma één of meer keer veranderd worden. De variabelen uit tabel 2.1 kunnen er na een tijdje bijvoorbeeld uitzien als getoond in tabel 2.2. Kleur en zijde zijn van waarde veranderd, maar stap heeft nog de oude waarde. Variabelen en waarden
TABEL 2.2 naam
waarde
kleur zijde stap
"zwart" 80 17.5
Zijn in JavaLogo-programma’s in hoofdstuk 1 al variabelen gebruikt? Hoe kregen die een waarde?
5
Starten met programmeren
De parameters die we in paragraaf 2.1 van het vorige hoofdstuk gebruikt hebben in de zelfgedefinieerde methoden, zijn voorbeelden van variabelen. In de methode met kop vierkant(double zijde) staan bijvoorbeeld opdrachten pen.vooruit(zijde); zijde is hierin een variabele. Parameters van methoden krijgen een waarde als de bijbehorende opdracht gegeven wordt; de opdracht vierkant(80) bijvoorbeeld geeft de variabele zijde de waarde 80. Namen: regels en afspraken
In JavaLogo moeten alle namen (van variabelen, van methoden, van programma’s) aan bepaalde regels voldoen. Ze moeten altijd beginnen met een letter (een hoofdletter of een kleine letter) en mogen naast letters verder alleen cijfers en liggende streepjes (_) bevatten. Het is verder gebruikelijk om namen van programma’s altijd met een hoofdletter te laten beginnen en namen van variabelen en methoden altijd met een kleine letter. OPGAVE 2.3
Bekijk de volgende namen: n, Drie_hoek, tekenLijn, nummer3, 17deRij, @teken. a Welke namen voldoen aan de regels voor namen in JavaLogo? b Welke zijn volgens de afspraken geschikt als variabelenaam? 2.2
TOEKENNINGEN EN UITDRUKKINGEN
We hebben net al één manier gezien om een waarde te geven aan een variabele, namelijk door een opdracht te geven om een methode met parameters uit te voeren. Een tweede manier is de toekenning, waarvan we in paragraaf 1 al een voorbeeld zagen. In JavaLogo heeft een toekenning altijd de volgende vorm: variabele = waarde; Let op! = ‘wordt gelijk aan’
Links staat de variabele die een waarde moet krijgen, rechts staat die waarde. Daartussen in staat een gelijkteken, dat in dit geval gelezen moet worden als ‘wordt gelijk aan’ en niet als ‘is gelijk aan’. Zoals altijd in JavaLogo, eindigt de opdracht met een puntkomma. Eenvoudige voorbeelden van toekenning zijn: kleur = "zwart"; zijde = 25; aantalHoeken = 8;
Uitdrukking
Soms moet de waarde aan de rechterkant eerst nog uitgerekend worden; er staat dan geen getal of een string, maar een uitdrukking. We geven weer een paar voorbeelden: aantalZijden = 20 - 4 * 3; hoek = 360 / aantalZijden; oppervlak = zijde * zijde; hoogte = zijde; a = (jaar % 19) + 1;
In het eerste voorbeeld krijgt de variabele zijde de waarde 20 – 12 = 8 (het sterretje wordt in JavaLogo gebruikt voor vermenigvuldiging). Het tweede voorbeeld is wat zinvoller: de waarde die wordt toegekend aan de variabele hoek, wordt berekend als 360 gedeeld door de waarde die
6
Leereenheid 2
Programmeren met herhaling en keuze
de variabele aantalZijden heeft. Heeft aantalZijden de waarde 8, dan wordt hoek gelijk aan 360 / 8 = 45. Heeft aantalZijden de waarde 12, dan wordt hoek gelijk aan 360 / 12 = 30. Het derde voorbeeld kent aan een variabele oppervlak de waarde zijde ∞ zijde toe. Het vierde voorbeeld geeft aan de variabele hoogte dezelfde waarde die zijde heeft. Het vijfde voorbeeld tenslotte is het voorbeeld uit paragraaf 1: aan de variabele a wordt de rest van de deling jaar/19 toegekend, verhoogd met 1. In (rekenkundige) uitdrukkingen kunnen dus getallen en variabelen voorkomen, samen met rekenkundige bewerkingen daarop: optellen (+), aftrekken (–), vermenigvuldigen (*), delen (/). Er zijn nog veel meer bewerkingen mogelijk, waar we er maar één van behandelen: de bewerking % neemt de rest bij deling. OPGAVE 2.4
Welke waarden hebben de variabelen a, b, c, d en e na de volgende reeks toekenningen? a b c d e
= = = = =
10; 2 * a * c / c %
a + 4; b; 100; 100;
We bekijken nog één bijzonder geval. Stel dat we een variabele met de naam bedrag hebben en we willen de waarde van die variabele met 10 verhogen. We kunnen dat als volgt opschrijven: bedrag = bedrag + 10;
Om deze toekenning te begrijpen, is het belangrijk om goed te beseffen dat de waarde aan de rechterkant altijd eerst wordt uitgerekend, en dat die pas daarna aan de variabele die links staat, wordt toegekend. Stel bijvoorbeeld dat de variabele bedrag vóór deze toekenning de waarde 60 heeft. De uitdrukking bedrag+10 heeft dan dus de waarde 70. Die waarde wordt vervolgens toegekend aan bedrag. Het resultaat is dan precies wat we wilden: de waarde van de variabele bedrag is met 10 opgehoogd. Dit voorbeeld illustreert een bezwaar tegen het gebruik in Java van het gelijkteken voor de toekenning. Als dat gelijkteken wordt gelezen als ‘is gelijk aan’ in plaats van als ‘wordt gelijk aan’, dan staat hierboven onzin: de waarde van bedrag kan niet gelijk zijn aan diezelfde waarde plus tien (wiskundig gezien heeft de vergelijking bedrag = bedrag + 10 geen oplossing). Sommige programmeertalen vermijden dit soort verwarring door de toekenning te schrijven als :=, dus in dit geval bedrag := bedrag + 10. Helaas is daar in Java niet voor gekozen. OPGAVE 2.5
Schrijf de volgende drie opdrachten als toekenningen: a verlaag de waarde van een variabele teller met 1 b verdubbel de waarde van een variabele a c maak de waarde van een variabele b tien keer zo klein.
7
Starten met programmeren
2.3
VARIABELEN IN JAVALOGO
In een programma in JavaLogo kunnen drie soorten variabelen voorkomen. – Variabelen die in het hele programma gebruikt kunnen worden, ofwel programmavariabelen. – We hebben al gezien dat de parameters van de zelfgedefinieerde methoden variabelen zijn die een waarde krijgen als er een bijbehorende opdracht wordt uitgevoerd. – Het is tenslotte ook mogelijk om binnen een methode nog extra variabelen te gebruiken; we spreken in dat geval van lokale variabelen. We bekijken deze drie vormen een voor een. Programmavariabelen
Aan het begin van een JavaLogo-programma, meteen na de kop, kunnen we variabelen opnemen die overal in het programma gebruikt mogen worden. Figuur 2.2 toont een programma VarVoorbeeld met drie programmavariabelen stap, hoek en kleur. 1
import logotekenap.*;
5
public class VarVoorbeeld extends TekenApplet { String kleur; double hoek; double stap; public void initialiseer() { kleur = "rood"; hoek = 45; stap = 100; }
10
15
public void tekenprogramma() { pen.aan(kleur); pen.rechts(hoek); pen.vooruit(stap); }
20
} FIGUUR 2.2
Het programma VarVoorbeeld heeft drie programmavariabelen.
In regels 5-7 staan de drie programmavariabelen genoemd. Van elke programmavariabele wordt eerst het type en dan de naam vermeld; we noemen dat ook wel declaratie. In het algemeen heeft een variabeledeclaratie de volgende vorm: Declaratie
type naam;
We zullen declaraties van programmavariabelen altijd meteen na de kop van het programma plaatsen en iedere declaratie op een aparte regel zetten (Java laat wat variaties hierop toe, maar die behandelen we niet). In de methode initialiseer geven we de programmavariabelen een (eerste) waarde. De variabele kleur krijgt de waarde "rood", hoek krijgt de waarde 45, en stap de waarde 100. Die waarde moet kloppen met het
8
Leereenheid 2
Programmeren met herhaling en keuze
type: aan variabelen van type double worden getallen toegekend, aan variabelen van type String tekstwaarden als "rood" of "zwart". In de methode tekenprogramma maken we gebruik van die waarden: in plaats van pen.aan("rood"), schrijven we pen.aan(kleur). Voor de waarden van parameters in opdrachten geldt hetzelfde als voor de waarde in de rechterkant van een toekenning: de waarde mag geschreven worden als iets dat eerst uitgerekend moet worden. We zouden dus ook bijvoorbeeld mogen schrijven: pen.rechts(hoek – 15) of pen.vooruit(stap / 2 + 230). Als we dat willen, dan mogen we in tekenprogramma() en/of in zelfgedefinieerde methoden, nog andere waarden toekennen aan de programmavariabelen. Voorbeelden daarvan zullen we in de volgende paragrafen zien. OPGAVE 2.6
a In paragraaf 1.1 van hoofdstuk 1 hebben we twee bergen getekend. We zouden in die tekening het een en ander kunnen variëren, zoals aangegeven in figuur 2.3: we zouden de hoogte, de hoek van de top (hoe kleiner die hoek, hoe steiler de berg) of de afstand tussen de twee bergen anders kunnen kiezen. Schrijf een JavaLogo-programma met hoek, hoogte en afstand als programmavariabelen. Voer eventueel uw programma in bij JCreator en experimenteer met verschillende waarden voor de programmavariabelen. b Ziet u een voordeel aan het gebruik van programmavariabelen boven het direct wijzigen van de getallen in het programma uit hoofdstuk 1?
180 – hoek hoogte
hoek
hoogte – 20
90 + hoek/2 afstand
FIGUUR 2.3
Parameter
De hoogte, de tophoek en de afstand kunnen variabel genomen worden. Parameters zijn al behandeld in paragraaf 2.1 van het vorige hoofdstuk. We hoeven daar nog maar één opmerking aan toe te voegen. Stel, we schrijven een methode met parameters, bijvoorbeeld met de kop public void zeshoek(String kleur, double zijde)
Omdat kleur en zijde variabelen zijn, kunnen er in principe binnen de methode nieuwe waarden aan worden toegekend, bijvoorbeeld: public void zeshoek(String kleur, double zijde) { pen.aan(kleur); pen.vooruit(zijde); kleur = "zwart"; zijde = zijde – 10; ...
9
Starten met programmeren
}
Dit komt de begrijpelijkheid van uw programma echter meestal niet ten goede, we raden dat dus af. Lokale variabele
Tot slot kijken we naar lokale variabelen. Programmavariabelen zijn variabelen die in alle methoden gebruikt mogen worden: de waarde mag overal gebruikt worden in uitdrukkingen en veranderd worden in toekenningen. Soms is een variabele echter alleen nodig binnen één methode. We hebben dan geen programmavariabelen nodig, maar kunnen in plaats daarvan een variabele declareren en gebruiken binnen die methode zelf. Een dergelijke variabele heet een lokale variabele. Buiten die ene methode is deze variabele onbekend. Figuur 2.4 toont als voorbeeld een herformulering van een deel van het tekenprogramma uit figuur 1.12 in hoofdstuk 1, dat vijf steeds kleinere vierkanten tekent (zie ook figuur 1.11). We zullen zien dat het gebruik van een lokale variabele hier een interessant effect heeft. 1
5
// tekent vijf rode vierkanten van afnemende grootte public void tekenprogramma() { double z; double afstand; pen.uit(); pen.links(90); pen.vooruit(230); pen.rechts(90);
10
z = 100; afstand = 20; 15
vierkant(z); naarRechts(z + afstand); z = z - 20; vierkant(z); naarRechts(z + afstand); z = z - 20;
20
vierkant(z); naarRechts(z + afstand); z = z - 20;
25
vierkant(z); naarRechts(z + afstand); z = z - 20; 30
vierkant(z); naarRechts(z + afstand); z = z - 20; 34
}
FIGUUR 2.4
Lokale variabelen in methode tekenprogramma
De regels 4 en 5 bevatten de declaratie van twee lokale variabelen, met de namen z en afstand. De declaraties zien er precies zo uit als die van programmavariabelen: ze noemen het type van de variabele en de naam. Ook hier moet de waarde die aan de variabelen wordt toegekend, altijd kloppen met dat type.
10
Leereenheid 2
Programmeren met herhaling en keuze
In regels 7-10 wordt de pen bewogen naar het beginpunt van de tekening. In regels 12 en 13 krijgen z en afstand een eerste waarde: z wordt gelijk aan 100 en afstand aan 20. De variabele afstand zal die waarde steeds houden, maar de variabele z niet. Kijk maar naar regels 15-18: eerst tekenen we een vierkant met zijde z, dan bewegen we de pen naar rechts en dan maken we z 20 pixels kleiner. Dit herhalen we nog vijf keer, voor elk van de vierkanten. U ziet, dat we nu vijf keer precies dezelfde serie van opdrachten hebben, terwijl we toch vijf keer een ander vierkant tekenen! In de volgende paragraaf zult u dit voorbeeld met behulp van een herhaling schrijven. OPGAVE 2.7
In regel 15 van figuur 2.4 staat de opdracht vierkant(z). De methode vierkant ziet er als volgt uit: public void vierkant(double zijde) { pen.vulAan("rood"); pen.vooruit(zijde); ... }
Mogen we de variabele z ook gebruiken binnen deze methode en dus bijvoorbeeld schrijven pen.vooruit(z) in plaats van pen.vooruit(zijde)? Tabel 2.3 vat de overeenkomsten en verschillen samen tussen de drie soorten variabelen, door voor elke soort te tonen waar de declaratie staat, hoe de variabele een waarde krijgt en waar in het programma de variabele gebruikt mag worden. TABEL 2.3
Drie soorten variabelen programmavariabelen
parameters
lokale variabelen
declaratie
na kop programma
in kop methode
na kop methode
krijgt waarde door
toekenning
opdracht met parameters
toekenning
te gebruiken
overal
binnen methode
binnen methode
Tot slot van deze paragraaf maken we nog wat opmerkingen over de naamgeving van variabelen. – Programmavariabelen mogen overal gebruikt worden. We zorgen er daarom voor, dat parameters en lokale variabelen altijd andere namen krijgen dan de programmavariabelen. – Als een methode een parameter heeft met een bepaalde naam, dan mag die methode uiteraard geen lokale variabele hebben met dezelfde naam. – Verschillende methoden mogen wel dezelfde naam gebruiken voor een parameter of een lokale variabele. Er is dus niets tegen een methode driehoek met een parameter zijde en een methode vierkant met een parameter die ook zijde heet. Diezelfde naam mag dan ook nog voor een lokale variabele gebruikt worden in een derde methode, zoals tekenprogramma. We hadden de lokale variabele z uit figuur 2.4 dus ook best zijde mogen noemen (maar we kunnen ons voorstellen dat u dat verwarrend zou vinden).
11
Starten met programmeren
3
Herhalingsopdrachten
3.1
VOORBEELD VAN EEN HERHALING
We kunnen in JavaLogo een opdracht of een reeks opdrachten een aantal keren herhalen. Als eerste voorbeeld kijken we naar de methode vierkant, die een rood vierkant tekent (zie het eind van paragraaf 2 van hoofdstuk 1). Deze bevat vier keer achter elkaar precies dezelfde opdrachten: pen.vooruit(zijde); pen.rechts(90);
Figuur 2.5 toont een versie van deze methode waarin gebruikgemaakt wordt van een herhaling. 1
public void vierkant(double zijde) { int teller;
5
pen.vulAan("rood"); teller = 1; while (teller <= 4) { pen.vooruit(zijde); pen.rechts(90); teller = teller + 1; } pen.vulUit();
10
15
}
FIGUUR 2.5
Methode vierkant met herhaling
We willen de twee opdrachten pen.vooruit(zijde) en pen.rechts(90) vier keer herhalen. Om op tijd te stoppen, moeten we bijhouden hoe vaak we deze opdrachten al hebben uitgevoerd. We gebruiken daarvoor een lokale variabele teller, die in regel 3 wordt gedeclareerd. int
De teller is van een type dat we nog niet eerder hebben gezien, namelijk int. Dit type wordt gebruikt voor gehele getallen, dus bijvoorbeeld 1, 2, 0, –17, 1024 (int is een afkorting van het Engelse woord integer, dat geheel getal betekent). We komen straks nog terug op het type int en het verschil tussen int en double, maar merken nu vast op, dat we tellers altijd het type int zullen geven. In regel 7 geven we deze teller de waarde 1. In regel 8 begint de herhaling. De betekenis van de code in regel 8 is: ‘herhaal de volgende reeks opdrachten, zolang de waarde van de variabele teller kleiner dan of gelijk aan 4 is’. Zodra de teller groter is geworden dan 4, zal de herhaling stoppen. JavaLogo moet precies kunnen zien welke opdrachten herhaald moeten worden; deze staan daarom tussen accolades. Het gaat dus om de opdrachten op regels 10, 11 en 12. De eerste twee zijn de bekende opdrachten pen.vooruit(zijde) en pen.rechts(90); de derde opdracht verhoogt de teller met 1.
12
Leereenheid 2
Programmeren met herhaling en keuze
Tabel 2.4 laat schematisch zien wat er gebeurt tijdens het uitvoeren van de herhalingsopdracht op regels 8-13. TABEL 2.4
Wat gebeurt er bij het uitvoeren van de herhaling?
teller
teller <= 4?
effect
1 2 3 4 5
1 <= 4 is waar 2 <= 4 is waar 3 <= 4 is waar 4 <= 4 is waar 5 <= 4 is onwaar
pen tekent zijde en draait; teller wordt 2 pen tekent zijde en draait; teller wordt 3 pen tekent zijde en draait; teller wordt 4 pen tekent zijde en draait; teller wordt 5 herhaling is klaar
OPGAVE 2.8
Deze opgave is bedoeld als vingeroefening; u hoeft de methoden dus niet per se op de computer uit te proberen. a Schrijf een methode achthoek(double zijde), die een niet-gevulde regelmatige achthoek tekent met de gegeven zijde. U mag aannemen dat de pen al aan staat. De benodigde draai is nu 45 graden. b Bij het tekenen van een gelijkzijdige driehoek wordt steeds 120° (360°/3) naar rechts gedraaid. Voor een vierkant is de draai 90° (360°/4) en voor een achthoek 45° (360°/8). Voor een regelmatige figuur met n hoeken bedraagt de benodigde draai dus 360°/n. Hierbij is n uiteraard altijd een geheel getal. Schrijf een methode met kop public void nhoek(int n, double zijde)
die een (niet-gevulde, zwarte) regelmatige n-hoek tekent. U mag ook nu aannemen dat de pen al aanstaat. c Hoe denkt u dat de figuur er uitziet die wordt getekend met behulp van de opdracht nhoek(360, 1)? Dat is dus een 360-hoek met zijde 1. int en double
Vanaf nu gebruiken we twee typen voor getallen: int voor gehele getallen en double voor alle getallen (heel én gebroken). Bij de keuze tussen int en double zullen we ons aan de volgende eenvoudige regel houden. – Variabelen die we gebruiken in penbewegingen (vooruit, links, rechts), geven we altijd het type double, zelfs als we van plan zijn om steeds een heel aantal pixels te bewegen of te draaien. We kunnen ons dan gemakkelijk later bedenken en er toch een gebroken getal aan toekennen. – Variabelen die we gebruiken als teller of voor aantallen (zoals het aantal hoeken of het aantal zijden van een figuur), krijgen type int. In dit geval zullen we ons immers nooit bedenken; we kunnen een herhaling nu eenmaal niet 3.7 keer uitvoeren of een 7.5-hoek tekenen.
!= betekent ‘ongelijk aan’ in Java
Waarom gebruiken we niet gewoon altijd double, ook voor tellers en aantallen? Het probleem daarmee is, dat tests op (on)gelijkheid met waarden van type double niet altijd goed gaan. Een herhaling die begint met while (teller != 10) zou bijvoorbeeld wel eens nooit kunnen stoppen als teller van het type double is, ook als teller begint op 0 en bij elke doorgang met 1 verhoogd wordt. Is teller van het type int, dan gaat het wel goed. Dat heeft te maken met de manier waarop getallen in een computergeheugen opgeslagen worden. Getallen van type int worden precies opgeslagen; bij getallen van type double wordt de precieze waarde zo goed mogelijk benaderd. Die onnauwkeurigheid maakt, dat de voorwaarde (teller != 10) onverwacht niet waar kan blijken als teller van type double is: teller is na tien doorgangen wel bijna gelijk aan 10, maar toch net niet helemaal.
13
Starten met programmeren
3.2
ALGEMENE VORM VAN DE HERHALINGSOPDRACHT
De algemene vorm van de herhalingsopdracht is: Herhalingsopdracht
Algemene vorm
while (voorwaarde) { opdracht1; opdracht2; ... opdrachtn; }
Als er slechts één opdracht herhaald moet worden, mogen de accolades ook weggelaten worden; dat komt in deze cursus echter nooit voor. We beschrijven nu eerst hoe een herhaling wordt uitgevoerd en kijken dan wat meer in detail naar achtereenvolgens de voorwaarde en de opdrachten. Uitvoering van herhalingsopdracht
Bij de uitvoering van een herhalingsopdracht wordt eerst bepaald of de voorwaarde waar of niet waar is. Is deze waar, dan wordt de reeks opdrachten uitgevoerd. Het testen van de voorwaarde en de uitvoering van de reeks opdrachten herhaalt zich tot de voorwaarde een keer niet waar blijkt; dan wordt de reeks opdrachten niet meer uitgevoerd, maar gaat het programma verder met de eerste opdracht na de herhaling (als die er is; anders is de methode waarin de herhaling staat, klaar). De uitvoering van een herhalingsopdracht begint én eindigt dus altijd met het testen van de voorwaarde. Het is ook mogelijk dat de voorwaarde de eerste keer al meteen niet waar is; in dat geval wordt de reeks opdrachten geen enkele keer uitgevoerd. Dat is bijvoorbeeld het geval bij de volgende (onverstandige) herhalingsopdracht: teller = 1; while (teller > 10) { pen.vooruit(1); pen.rechts(1); }
Wat zou er gebeuren als we in deze code de voorwaarde wijzigen in (teller > 0)? In dat geval is de voorwaarde waar en worden de twee opdrachten uitgevoerd. De waarde van teller blijft echter steeds gelijk aan 1 en dus blijft de voorwaarde (teller > 0) altijd waar. Het programma zal daarom altijd in de herhaling blijven hangen. Het stopt niet en blijkt dan ook niets te tekenen. U zult het met de hand moeten stoppen (bijvoorbeeld door het DOS-venster dat bij het uitvoeren ook wordt gebruikt, te sluiten). Het blijven hangen in de herhaling kan ook gebeuren als u de accolades om de opdrachten vergeet. JavaLogo herhaalt dan alleen de eerste opdracht; als die de variabele in de voorwaarde niet wijzigt, dan stopt het programma dus niet. Herhaling kan oneindig doorgaan
Pas op!
Herhalingsopdrachten zijn dus in zekere zin gevaarlijk: u kunt per ongeluk een herhaling schrijven die altijd door blijft gaan.
14
Leereenheid 2
Voorwaarde
Programmeren met herhaling en keuze
We gaan de voorwaarde bekijken. Wij zullen alleen eenvoudige voorwaarden gebruiken, die twee waarden met elkaar vergelijken. De taalelementen die u hiervoor in Java kunt gebruiken, staan in tabel 2.5. In herhalingsopdrachten zullen we alleen getalwaarden met elkaar vergelijken; de vergelijkingen van Stringwaarden hebben we pas in de volgende paragraaf nodig. TABEL 2.5 Voorwaarden in Java v1 en v2 zijn getalwaarden; s1 en s2 zijn Stringwaarden voorwaarde
betekenis*
(v1 == v2) (v1 != v2) (v1 > v2) (v1 < v2) (v1 >= v2) (v1 <= v2) (s1.equals(s2)) (!s1.equals(s2))
waar als v1 en v2 gelijk zijn waar als v1 en v2 niet gelijk zijn waar als v1 groter is dan v2 waar als v1 kleiner is dan v2 waar als v1 groter is dan v2 of gelijk is aan v2 waar als v1 kleiner is dan v2 of gelijk is aan v2 waar als s1 en s2 gelijk zijn waar als s1 en s2 niet gelijk zijn
* waar als voorwaarde geldt, anders onwaar
Gelijkheid van getallen: ==
Merk op dat de test op gelijkheid van getallen een dubbel gelijkteken gebruikt. Het enkele gelijkteken is immers al in gebruik voor de toekenning! Herinner u ook, dat testen op gelijkheid of ongelijkheid van waarden van het type double, een hachelijke zaak is.
Gelijkheid van strings: equals
Gelijkheid van Stringwaarden wordt op een andere manier getest. We schrijven bijvoorbeeld niet (kleur == "zwart"), maar kleur.equals("zwart"). Verder mag het ook bij voorwaarden voorkomen dat de te vergelijken waarden eerst uitgerekend moeten worden: er mogen dus aan beide kanten variabelen of uitdrukkingen staan. De volgende voorwaarden zijn dus allemaal toegestaan (aangenomen dat de variabelen a, b en c gedeclareerd zijn en een waarde hebben gekregen): (a > 13.5) (c * c == a - 1) (b * b - 4 * a * c > 0) OPGAVE 2.9
a Stel dat a de waarde 10 heeft, b de waarde 6 en c de waarde –3. Geef voor elk van de drie voorgaande voorwaarden aan, of deze waar is. b Iemand schrijft een herhalingsopdracht van de vorm ‘while (a = 0) {...}’. Worden de opdrachten binnen de accolades uitgevoerd? U kunt ook samengestelde voorwaarden uitdrukken door gebruik te maken van de logische operatoren && (EN) en || (OF). In bijvoorbeeld while ((a > 0 && b > 0) || c > 0) is de voorwaarde waar als of zowel a als b positief zijn, of als c positief is (of allebei). We gaan hier verder niet op in.
Opdracht
Tot slot kijken we naar de opdrachten zelf. Zo’n opdracht binnen een herhaling kan van alles zijn: een opdracht aan pen of tekenblad, een opdracht die een zelfgedefinieerde methode aan het werk zet, een toekenning, maar ook een keuzeopdracht of een herhalingsopdracht. Het
15
Starten met programmeren
is dus toegestaan om herhalingsopdrachten binnen elkaar te schrijven. We zullen dat overigens in dit hoofdstuk niet doen, omdat we vanwege de begrijpelijkheid liever gebruikmaken van extra methoden. Een voorbeeld daarvan zullen we zien in paragraaf 4. OPGAVE 2.10
Figuur 2.4 toont een versie van het tekenprogramma voor vijf rode vierkanten waarin vijf keer dezelfde serie van drie opdrachten staat. Schrijf een versie die de herhalingsopdracht gebruikt. U mag het uitproberen op de computer, maar dat hoeft niet per se. Aanwijzing: u kunt een teller gebruiken, maar u kunt ook testen op de waarde van de variabele zijde. 3.3
EEN TOEPASSING
Tot slot van deze paragraaf gaan we een volledig programma schrijven en uitvoeren in JavaLogo en wel een programma dat een gele spiraal tekent op een zwarte achtergrond, als getoond in figuur 2.6.
FIGUUR 2.6
Gele spiraal op zwarte achtergrond
We zagen eerder al hoe een cirkel getekend kan worden, namelijk door steeds een stap naar voren te gaan en dan 1° te draaien. Hoe groter de stap is, hoe groter de cirkel wordt. Als we de stap steeds iets kleiner maken, wordt de cirkel ook langzamerhand kleiner en krijgen we een spiraal. In figuur 2.6 zijn we begonnen met een stap van 2 en hebben we die waarde na iedere stap vooruit verkleind met 0,0005, tot de stap 0 is geworden. OPGAVE 2.11
a We gaan een JavaLogo-programma schrijven met de naam Spiraal. – Vul eerst de methode initialiseer in; zorg dat deze de achtergrond zwart maakt. Schrijf dan de methode tekenprogramma. – Declareer lokale variabelen stap (voor de grootte van de stap) en dstap (de waarde van dstap geeft aan hoeveel kleiner de stap steeds wordt). – Zet de pen uit en beweeg die een stuk naar links (bijvoorbeeld 200 pixels). – Geef stap de beginwaarde 2 en dstap de waarde 0.0005. – Teken de spiraal met behulp van een herhalingsopdracht die door blijft gaan zolang stap nog groter is dan 0.
16
Leereenheid 2
Programmeren met herhaling en keuze
b Voer het programma uit op de computer. Experimenteer met andere waarden van stap en dstap. Welk effect heeft het groter of kleiner maken van stap? En van dstap? 4
Keuzeopdrachten
4.1
TWEE VOORBEELDEN
Naast de mogelijkheid om opdrachten te herhalen, bieden hogere programmeertalen ook altijd de mogelijkheid om opdrachten al dan niet uit te voeren, afhankelijk van een bepaalde voorwaarde. We beginnen weer met voorbeelden. In opgave 2.8 schreven we een methode nhoek, die een regelmatige nhoek tekende. In figuur 2.7 gebruiken we die methode om, afhankelijk van de waarde van nummer, een rode cirkel of een blauw vierkant te tekenen. 1
5
10
15
public void vierkantOfCirkel(int nummer) { if (nummer % 2 == 0) { pen.vulAan("blauw"); nhoek(4, 50); pen.vulUit(); } else { pen.vulAan("rood"); nhoek(360, 1); pen.vulUit(); } pen.vooruit(100); }
FIGUUR 2.7
Teken een blauw vierkant of een rode cirkel.
De keuzeopdracht begint op regel 3 en loopt tot en met regel 14. Op de eerste regel staat het woord if, gevolgd door een voorwaarde. Daarna komt een reeks opdrachten (regels 5-7), dan het woord else (regel 9) en dan een tweede reeks opdrachten (regels 10-14). Om beide reeksen staan accolades. Bij de uitvoering van de opdracht wordt eerst bepaald of aan de voorwaarde is voldaan. In dit geval wordt gekeken of de rest van de deling nummer/2 gelijk is aan 0, ofwel: er wordt gekeken of nummer even is. Is de voorwaarde waar, dan wordt alleen de eerste reeks opdrachten uitgevoerd: als nummer even is, wordt een blauw vierkant getekend. Is de voorwaarde niet waar, dan wordt alleen de tweede reeks opdrachten uitgevoerd: er wordt een rode cirkel getekend. In beide gevallen gaat de uitvoering daarna verder met de verplaatsing van de pen op regel 15. In dit voorbeeld kiezen we tussen twee reeksen opdrachten. Het kan echter ook zijn dat we een bepaalde reeks opdrachten alleen willen uitvoeren als aan een bepaalde voorwaarde is voldaan; de keuzeopdracht heeft dan een iets andere vorm. Een voorbeeld ontlenen we aan de methode nhoek, met parameters n en zijde. We kunnen alleen een nhoek tekenen als n tenminste gelijk is aan 3;
17
Starten met programmeren
2-hoeken en 1-hoeken bestaan immers niet. Figuur 2.8 toont een versie van de methode nhoek die dit controleert. 1
public void nhoek(int n, double zijde) { int teller;
5
if (n >= 3) { teller = 1; while (teller <= n) { pen.vooruit(zijde); pen.rechts(360/n); teller = teller+1; } }
10
15
}
FIGUUR 2.8
Teken een regelmatige n-hoek als n ≥ 3.
De keuzeopdracht loopt van regel 5 tot en met regel 14. Regel 5 bevat weer een voorwaarde: is n tenminste 3? Is deze waar, dan worden de opdrachten uitgevoerd die tussen de accolades op regel 6 en regel 14 staan. Hoeveel opdrachten zijn dat? Dat ligt er een beetje aan hoe we tellen, maar in feite zijn het maar twee opdrachten: de toekenning aan teller en de herhalingsopdracht die begint op regel 8 en eindigt op regel 13. Binnen die herhalingsopdracht staan ook weer drie opdrachten. In dit geval is er geen else-gedeelte met een tweede reeks opdrachten. Als de voorwaarde waar is, worden de toekenning en de herhaling uitgevoerd; als de voorwaarde niet waar is, worden die overgeslagen en is de methode meteen klaar. OPGAVE 2.12
Beschrijf wat er gebeurt bij de uitvoering van de volgende methode. De opdracht naarRechts(stap) verplaatst de pen stap pixels naar rechts. public void rij(int aantal) { int teller; pen.aan("zwart"); if (aantal < 10) { teller = 1; while (teller <= aantal) { if (teller % 2 == 0) { nhoek(3, 50); } else { nhoek(5, 30); } naarRechts(70); teller = teller + 1;
18
Leereenheid 2
Programmeren met herhaling en keuze
} } } 4.2
ALGEMENE VORMEN VAN DE KEUZEOPDRACHT
In het algemeen neemt de keuzeopdracht één van de volgende twee vormen aan (we tonen ze naast elkaar): Keuzeopdracht
Vormen
if (voorwaarde) { opdrachti1; opdrachti2; ... opdrachtin; } else { opdrachte1; opdrachte2; ... opdrachten; }
if (voorwaarde) { opdracht1; opdracht2; ... opdrachtn; }
Als een reeks maar uit één opdracht bestaat, mogen de accolades om die reeks weggelaten worden. Anders dan bij de herhaling, komt dat wel vaak voor. De binnenste keuzeopdracht in opgave 2.12 zou bijvoorbeeld ook als volgt geschreven mogen worden: if (teller % 2 == 1) nhoek(3, 50); else nhoek(5, 30);
De uitvoering van keuzeopdrachten is op grond van de voorbeelden al voldoende duidelijk gemaakt. Zoals we al gezien hebben, mogen binnen een keuzeopdracht alle soorten opdrachten staan: toekenningen, opdrachten aan de pen of ter uitvoering van een zelfgedefinieerde methode en ook herhalingsopdrachten of andere keuzeopdrachten. Eén speciaal geval is interessant om even apart te bekijken. De eerste vorm van de keuzeopdracht geeft een keuze uit twee mogelijkheden, maar wat als we een keuze uit 3 of meer mogelijkheden willen? Stel bijvoorbeeld dat we in plaats van afwisselend een drie- en een vijfhoek, afwisselend een driehoek, een vierkant en een vijfhoek willen tekenen. We kunnen dit als volgt opschrijven (met een extra opdracht naarRechts(70) erachteraan, om de uitleg te vergemakkelijken): if (teller % 3 == 0) nhoek(3, 50); else if (teller % 3 == 1) nhoek(4, 40); else nhoek(5, 30); naarRechts(70);
Hier staat een keuzeopdracht waarbij beide reeksen maar één opdracht bevatten, en die we dus zonder accolades schrijven. In de eerste reeks is
19
Starten met programmeren
dat de opdracht nhoek(3, 50); in de tweede reeks is het een keuzeopdracht. Laten we nagaan wat er gebeurt als teller respectievelijk de waarde 12, 13 en 14 heeft. Als teller gelijk is aan 12, dan is de voorwaarde (teller % 3 == 0) waar, want 12 is zonder rest deelbaar door 3. De opdracht nhoek(3, 50) wordt uitgevoerd, maar de keuzeopdracht na de eerste else wordt niet uitgevoerd. Na het tekenen van de driehoek gaat het programma dus verder met de opdracht naarRechts(70). Als teller gelijk is aan 13, dan is de eerste voorwaarde onwaar. De opdracht nhoek(3, 50) wordt overgeslagen en de keuzeopdracht na de eerste else wordt uitgevoerd. Die uitvoering begint met de voorwaarde (teller % 3 == 1) en die is waar. Dus wordt de opdracht nhoek(4, 40) uitgevoerd, maar de opdracht nhoek(5, 30) niet. Het programma tekent een vierkant en gaat dan verder met naarRechts(70). Ook als teller gelijk is aan 14, is de eerste voorwaarde onwaar, zodat ook nu het tekenen van de driehoek wordt overgeslagen en de tweede keuzeopdracht wordt uitgevoerd. Ook de voorwaarde in die opdracht (teller % 3 == 1) is nu onwaar. De opdracht nhoek(4, 40) wordt overgeslagen en nhoek(5, 30) wordt uitgevoerd. Er wordt dus nu alleen een vijfhoek getekend. Voor een keuze uit 4 werkt het precies zo. Vaak wordt het inspringen na de eerste else in dit geval achterwege gelaten en wordt direct geschreven if (teller % 3 == 0) nhoek(3, 50); else if (teller % 3 == 1) nhoek(4, 40); else nhoek(5, 30); 4.3
EEN TOEPASSING
In de volgende opgave gaan we weer een volledig programma schrijven dat de tekening maakt zoals getoond in figuur 2.9.
FIGUUR 2.9
Splitsen van een probleem in deelproblemen
Een waaier van 25 gele, blauwe en rode vierkanten
Dit programma is iets complexer dan de programma’s die we eerder schreven. We gaan daarom niet meteen programmeren, maar we gaan eerst bedenken hoe we het programma gaan opzetten: we maken een ontwerp. We beginnen daarbij met het probleem in deelproblemen op te
20
Leereenheid 2
Programmeren met herhaling en keuze
splitsen. We kunnen het tekenen van een waaier bijvoorbeeld als volgt beschrijven: Teken een waaier Herhaal 25 keer: bepaal de kleur teken vierkant draai over hoek
We hebben het probleem nu gesplitst in drie deelproblemen, namelijk de kleur bepalen, een vierkant tekenen en draaien. We kunnen voor elk van die deelproblemen een aparte methode definiëren. Bij nader inzien is dat voor het laatste deelprobleem, het draaien, niet nodig: dat is immers maar een enkelvoudige opdracht. Maar voor het bepalen van de kleur en het tekenen van een vierkant nemen we wel aparte methoden op. Hoe bepalen we de kleur? Als we eenmaal een kleur hebben, kunnen we daarbij steeds de volgende kleur vinden: na geel komt blauw, na blauw rood en na rood weer geel. We hebben dus een programmavariabele kleur nodig en geven daar een beginwaarde aan. Het maakt niet veel uit welke; laten we maar "rood" kiezen (omdat we de kleur bepalen voor we een vierkant tekenen, wordt het eerste vierkant dan geel). Het bepalen van een kleur gaat als volgt: Bepaal de kleur als de kleur geel is, maak die dan blauw, als de kleur blauw is, maak die dan rood, als de kleur rood is, maak die dan geel.
Dit kunnen we makkelijk programmeren met behulp van een keuzeopdracht; hulpmethoden zijn daarbij niet meer nodig. De methode heeft ook geen parameters; hij wijzigt alleen de waarde van het programmavariabele kleur. Een vierkant tekenen ten slotte, hebben we al een aantal keer gedaan; daar hoeven we niet meer over na te denken. De methode tekent een gevuld vierkant in de huidige kleur (de waarde van de variabele kleur). Alle vierkanten zijn even groot; deze methode vierkant heeft dus geen parameters nodig. Met behulp van dit ontwerp is het nu niet meer al te moeilijk om het programma te schrijven. OPGAVE 2.13
Schrijf nu zelf het JavaLogo-programma Waaier. Teken 25 vierkanten met zijde 150 en draai elk vierkant tien graden verder naar links. Voer het programma ook uit op uw pc. Deze methode om een probleem in deelproblemen te splitsen en die eventueel ook weer in deelproblemen, kunt u ook toepassen bij tekeningen die veel ingewikkelder zijn, zoals de vlakvulling uit figuur 2.1 (zie ook paragraaf 6). Opmerking
In voor de hand liggende JavaLogo-tekeningen zit meer herhaling dan keuze; voor de meeste voorbeelden is herhaling dan ook eigenlijk
21
Starten met programmeren
genoeg. We zouden de waaier bijvoorbeeld ook kunnen tekenen zonder methode bepaalKleur(), door in elke stap van de herhaling drie vierkanten te tekenen: eerst een gele, dan een rode en tot slot een blauwe. Wie dat zelf geconstateerd heeft, heeft dus geen ongelijk. Bij complexere tekeningen kan een methode bepaalKleur zoals we die nu geschreven hebben, wel goede diensten bewijzen. Kijk bijvoorbeeld nog maar eens naar figuur 2.1. Driehoeken komen daar voor in drie kleuren en in twee standen; op één rij herhaalt het patroon zich dus pas na zes stappen. Op een volgende rij wordt datzelfde patroon wel weer aangetroffen, maar op een andere plaats. Dit voorbeeld is zonder keuzeopdracht dus lastig uit te werken. 5
Animatie
JavaLogo kent een voorziening waardoor vrij gemakkelijk eenvoudige animaties gemaakt kunnen worden. Daarvoor zijn twee dingen nodig. maakAnimatieMogelijk()
Ten eerste moet in de methode initialiseer de volgende opdracht worden opgenomen: maakAnimatieMogelijk();
In een programma met deze opdracht verschijnt bij uitvoering bovenin een knop animatie, als getoond in figuur 2.10.
FIGUUR 2.10
Knop voor animatie
Om die knop ook te kunnen bedienen, moet aan het programma een methode worden toegevoegd met de volgende structuur: public void animatie() { while (animatieLopend()) { ... // verander iets tekenOpnieuw(); } }
Zodra er nu op de knop animatie wordt geklikt, loopt de animatie en gaat JavaLogo de opdrachten in de herhaling uitvoeren, tot de animatie weer wordt stopgezet. Eén van die opdrachten is altijd tekenOpnieuw(). Die opdracht zorgt ervoor dat de methode tekenprogramma() wordt uitgevoerd, dus dat de hele tekening opnieuw wordt gemaakt. Ook de pen begint daarbij weer op zijn oude plek midden in de tekening en in zijn oorspronkelijk stand (omhoog). Omdat tekenOpnieuw() binnen de herhaling staat, hebben we nu geen tekening meer, maar een film, met iedere afzonderlijke tekening als filmbeeldje. Om de beelden ook te laten bewegen, moet er natuurlijk wel bij iedere herhaling iets veranderd zijn; meestal zal dat de waarde zijn van een of meer programmavariabelen. Voorbeeld
22
Leereenheid 2
Programmeren met herhaling en keuze
Als voorbeeld passen we het programma Waaier uit opgave 2.13 aan. In die opgave maakte u een waaier van 25 vierkanten, waarbij elk vierkant een hoek van 10° maakte met het vorige. We kunnen die hoek ook groter of kleiner kiezen. Figuur 2.11 toont twee voorbeelden van andere waarden, namelijk hoek = 35 en hoek = 121.
FIGUUR 2.11
Waaiers met andere hoeken tussen de vierkanten
We gaan een animatie maken waarbij de hoek begint op 0° en dan langzaam aangroeit. We hebben daarvoor een programmavariabele hoek nodig, van type double: public class Waaier extends TekenApplet { String kleur; double hoek;
De methode initialiseer() komt er als volgt uit te zien. public void initialiseer() { hoek = 0; maakAnimatieMogelijk(); }
De opdracht kleur = "rood", die eerst in initialiseer() stond, verplaatsen we naar tekenprogramma(); we willen immers dat de beginkleur voor ieder filmbeeldje opnieuw geel is. Verder is de hoek waarover gedraaid wordt, nu variabel. public void tekenprogramma() { int teller; kleur = "rood"; teller = 1; while (teller <= 25) { bepaalKleur(); vierkant(); pen.links(hoek); teller = teller+1; } }
23
Starten met programmeren
En dit is ten slotte de methode animatie: public void animatie() { while (animatieLopend()) { hoek = hoek + 0.05; tekenOpnieuw(); } }
Iedere keer dat de tekening opnieuw gemaakt wordt, is de hoek iets groter. De waarde van 0,05 hebben we proefondervindelijk bepaald: hoe groter die waarde, hoe sneller de animatie. Bij een te grote waarde gaat de animatie zo snel dat de afzonderlijke stadia niet meer te onderscheiden zijn. OPGAVE 2.14
Breng deze wijzigingen aan in het programma Waaier en kijk naar het effect. U kunt de animatie starten door op de knop animatie te klikken (daar komt dan stop op te staan) en weer stoppen door op dezelfde knop te klikken. In de volgende opgave gaat u een autootje laten rijden (zie figuur 2.12). Het gaat vooral om de animatie, we geven u daarom de opdrachten die het autootje tekenen.
FIGUUR 2.12
Dit autootje gaan we laten rijden.
OPGAVE 2.15
Schrijf een JavaLogo-programma met de naam Auto. a Neem in dit programma een methode nhoek op met parameters n, zijde en kleur, die een gevulde regelmatige n-hoek met de gegeven zijde en van de gegeven kleur tekent. b Schrijf ook een methode naarBegin, die de pen 100 pixels naar rechts verplaatst. c Definieer de methode tekenprogramma(), die het autootje tekent, als volgt: public void tekenprogramma() { pen.uit(); naarBegin(); nhoek(360, 0.3, "blauw"); // nhoek(4, 60, "rood"); // pen.rechts(90); pen.vooruit(60); pen.links(90); nhoek(360, 0.3, "blauw"); // nhoek(4, 35, "rood"); // }
eerste wiel achterkant
tweede wiel voorkant
Test het programma in deze vorm uit.
24
Leereenheid 2
Programmeren met herhaling en keuze
d Wijzig het programma nu zo, dat het autootje van links naar rechts over het scherm rijdt. Als het rechts verdwenen is, moet het links weer te voorschijn komen. Aanwijzingen – Houd er rekening mee, dat de pen bij iedere uitvoering van tekenprogramma() weer in het midden van het tekenblad staat. – De methode naarBegin bepaalt op welke plek het autootje vervolgens wordt getekend, dus daar komt nu de variatie in. – Herinner u, dat de methode vooruit van pen ook een negatief getal als parameter mag hebben; de pen beweegt dan achteruit. – Als het autootje helemaal links of helemaal rechts is, mag een deel buiten het tekenblad vallen. U ziet het dan echt het blad op en af rijden. Tot besluit van deze paragraaf maken we nog een tweetal algemene opmerkingen over JavaLogo. Ieder JavaLogo-programma is ook een Java-programma. Declaraties, toekenningen, voorwaarden, herhaling en keuze komen direct uit Java. We hebben echter van deze taal slechts een zeer beperkt aantal mogelijkheden behandeld. We hebben daarbij vooral gestreefd naar duidelijkheid en niet naar compactheid en zeker niet naar volledigheid. Met meer kennis van Java kunnen vrijwel alle programma’s korter worden opgeschreven en is uiteraard ook veel meer mogelijk dan we hier laten zien. Een enkele keer werkt in JavaLogo de tracemogelijkheid niet goed. Die fout treedt op wanneer in de loop van het programma een programmavariabele van waarde verandert, terwijl die zijn beginwaarde krijgt in de methode initialiseer. Als u daar tegenaan loopt, kunt u de fout voorkomen door de toekenning van beginwaarden aan de programmavariabele niet in initialiseer, maar in het tekenprogramma zelf te zetten. Wanneer in JavaLogo de tracemogelijkheid wordt gebruikt, wordt het tekenprogramma namelijk, net als bij animatie, feitelijk meer dan eens doorlopen. De eerste keer worden alle tekenopdrachten verzameld; daarna kunnen we er naar believen vooruit en achteruit doorheen lopen. 6
Drie uitdagende programma’s
Met behulp van hetgeen u in deze cursus geleerd hebt, kunt u nog veel meer leuke JavaLogo-programma’s schrijven. De programma’s uit de volgende opdrachten zijn daar drie voorbeelden van. Deze programma’s zijn wat moeilijker dan hetgeen we tot nu toe gedaan hebben. Als u er niet zelf uitkomt, dan kunt u mogelijk veel leren door de uitwerkingen goed te bekijken. OPGAVE 2.16
Schrijf een JavaLogo-programma dat de tekening maakt uit figuur 2.13. Klikken op de knop animatie moet ertoe leiden, dat de cirkels naar buiten gaan bewegen, waarbij binnenin steeds een nieuw cirkeltje ontstaat. De kleuren kunt u zelf kiezen (rood en roze, of groen en geel doen het aardig). Aanwijzingen – Schrijf eerst een methode cirkel(double stap, String kleur) die een gevulde cirkel van de gevraagde kleur tekent en waarbij de pen begint en
25
Starten met programmeren
eindigt in het middelpunt. De straal van een cirkel die wordt getekend door 360 keer stap pixels vooruit te gaan, is gelijk aan 360×stap/(2π). In JavaLogo schrijven we dat als (360 * stap)/(2 * Math.PI). – Teken de cirkels van buiten naar binnen. Neem de stapgrootte van de buitenste cirkel gelijk aan 7 en verklein de stapgrootte steeds met bijvoorbeeld 0.5. Ga door zolang de stap groter is dan 0. – Maak bij de animatie de stapgrootte van de buitenste cirkel steeds een klein beetje (bijvoorbeeld 0.04) groter. Er komen dan binnenin vanzelf cirkels bij. Als de stapgrootte groter is geworden dan 8, zet hem dan terug op 7.
FIGUUR 2.13
Concentrische, naar buiten bewegende cirkels
OPGAVE 2.17
Schrijf een JavaLogo-programma dat een animatie vertoont van een rondstuiterende bal. De tekening uit figuur 2.14 geeft aan dat de bal beweegt binnen een vierkant waarvan de zijkanten de kleuren rood, oranje, blauw en groen hebben. Klikken op de knop animatie moet er toe leiden dat de bal gaat bewegen. De bal moet terug stuiteren zodra deze een zijkant raakt. Bij aanraking van een zijkant dient de bal ook van kleur te veranderen en dan de kleur van de zijkant aan te nemen. Aanwijzingen - Gebruik twee globale variabelen, Xpositie en Ypositie, waarin u de positie van het middelpunt van de bal op het tekenblad opslaat. - Schrijf een methode omlijning() waarmee u de gekleurde zijkanten tekent en een methode bal() waarmee u een gevulde cirkel tekent om de bal weer te geven. De pen dient aan het begin en einde van beide methodes in het middelpunt van het tekenblad te staan en omhoog te wijzen. - Gebruik twee variabelen, stap en straal, waarin u de stapgrootte en de straal van de cirkel opslaat. Er geldt dat straal = 360×stap/(2π). U kunt hier de methode cirkel uit opgave 2.16 deels hergebruiken.
26
Leereenheid 2
Programmeren met herhaling en keuze
- Gebruik in de methode animatie() twee variabelen, Xstap en Ystap, waarin u de bewegingsrichting van de bal vastlegt. Bij elke volgende tekening zal de bal Xstap pixels bewegen in horizontale richting en Ystap pixels in verticale richting. De bal beweegt naar rechts als Xstap positief is en naar links als Xstap negatief is. Evenzo beweegt de bal naar boven als Ystap positief is en naar beneden als Ystap negatief is. U krijgt het leukste effect als u verschillende waarden kiest voor Xstap en Ystap. - Het stuiteren bij aanraking van een zijkant kunt u verkrijgen door Xstap en/of Ystap van teken te veranderen. Als de bal bijvoorbeeld naar rechts beweegt – Xstap is dan positief – en de rechter zijkant raakt, zal de bal vervolgens naar links gaan bewegen – Xstap wordt dan negatief. - Afhankelijk van de snelheid van uw computer, zal de bal erg snel over het scherm bewegen. Om de animatie wat te vertragen kunt u een wachtlus inbouwen in de methode animatie() waarin u bijvoorbeeld van 1 tot 10,000,000 telt.
FIGUUR 2.14
Rondstuiterende gekleurde bal
OPGAVE 2.18
Schrijf een JavaLogo-programma dat de vlakvulling uit figuur 2.15 tekent.
FIGUUR 2.15
Vlakvulling van driehoeken in drie kleuren
27