TOPIC D: Procedures.
Contents
PROCEDURE
Exercises
T1: SumDivisibleBy.
Wat is de output van het volgend programma?
Voer het uit met de debugger! Hier is de
documentatie (vind je in het menu onder Documentation => XDS
manual). Bemerk het verschil tussen F7 en CTRL-F7.
MODULE T1;
<* NOOPTIMIZE + *>
<* WOFF + *> (* geen warnings *)
FROM IO IMPORT RdChar, WrChar, WrStr, RdStr,
WrLn, RdCard, WrCard, RdInt, WrInt, RdReal, WrReal, WrFixReal,
RdBool, WrBool;
FROM RealMath IMPORT power, arctan, pi, cos, sin,
sqrt;
PROCEDURE IsSumDivisibleBy(x1, x2,
x3: INTEGER):
BOOLEAN;
VAR result: BOOLEAN;
BEGIN
IF ((x1 + x2) MOD x3) = 0 THEN
result := TRUE;
ELSE
result := FALSE;
END;
RETURN result;
END IsSumDivisibleBy;
VAR opl: BOOLEAN;
a,
b, c:
INTEGER;
BEGIN
WrLn;
opl := IsSumDivisibleBy(10, 6, 4);
WrBool(opl, 0); WrLn;
a := 5;
b := 3;
c := 3;
opl := IsSumDivisibleBy(a, b+c, c);
WrBool(opl, 0); WrLn;
END T1.
S1: Procedure definities
A. Schrijf de header ('eerste lijn')
voor
de volgende procedures. Schrijf ook op 1 lijn een voorbeeld waarin je
de procedure gebruikt (bvb y :=
MyProcedure(x); ).
- Een procedure die een cirkel tekent met een gegeven middelpunt en
straal.
- Een procedure die kijkt of een getal deelbaar is door een ander.
- Een procedure die een geheel getal op het scherm schrijft.
- Een procedure die de preciese afstand tussen 2 punten berekent.
B. Implementeer deze laatste
procedure.
- Met power bereken je een macht, maar deze neemt
alleen positieve getallen als base,
simpeler
is
a*a
te
doen
voor
een
kwadraat.
- Met sqrt bereken je de vierkantswortel.
- Documentatie: zie
onderaan.
S2: Piramides
Start met dit . Hier is
de code van de JJ3D 3D engine.
Zie ook de documentatie
over JJ3D.
- Maak een procedure die een piramide tekent met een bepaalde
hoogte en als grondvlak een
vierkant in het XY-vlak.
- Teken 50 piramides op een lijn evenwijdig met de X-as,
één piramide om de 30 pixels. Neem als hoogte 300.
- Neem nu als hoogte 300 ×
de sinus-functie waarbij je de x
als de hoek in graden neemt.
- Maak er een animatie van. Elke piramide wordt om de beurten
getekend, van links naar rechts. In
topic
B
zagen
we een voorbeeld van animatie.
S3: Zuilen
- Teken een zuil door 5 cilinders met een verschillende kleur op
elkaar te stapelen en er een blok op te zetten.
- Maak een procedure die een zuil op bepaalde positie met een
bepaalde radius en hoogte. Zet de code erin. De grootte van de
cilinders bepaal je adhv de totale hoogte van de zuil
- Teken een rij van 8 zuilen in de Y-richting.
- Teken 2 van die rijen naast elkaar, zet er een dak op en je hebt
een tempel.
- Zet deze code in een procedure die een tempel van een zekere
hoogte tekent op een bepaalde positie
S4: Procedure definities
Schrijf de header ('eerste lijn') voor
de volgende procedures. Schrijf ook op 1 lijn een voorbeeld waarin je
de procedure gebruikt (bvb WrCard(x,
0); ).
- Een procedure die een kabelbrug tekent zoals in S6 van Topic A.
- Een procedure die de gemiddelde afstand van een aantal
punten tot de oorsprong berekent. De coordinaten van de punten worden
met behulp van arrays meegegeven (in
deze
oefening zie je een voorbeeld van zulke arrays).
- Een procedure die een deel van een circel tekent (een
'taartpunt'), van 1 hoek tot een andere.
S5: Van cilinder tot koeltoren
Start met deze code om punten
van een cirkel op te slaan (ook reeds gebruikt in oefening
S3
van Topic C). Zie
ook de documentatie over
JJ3D.
- Vul 2 arrays met de punten van 1 cirkel, 1 array voor de
x-coördinaten
en 1 voor de y-coördinaten. Teken met behulp van deze arrays 2
cirkels evenwijdig met het XY-vlak: 1 op hoogte 0 en een op hoogte 400.
- Tip: definieer de
arrays van 0 tot AANTAL-1, dit zal het oplossen
van deel 3 vergemakkelijken!
- Ter herinnering: de parameterische vergelijking van de cirkel is
x0
+
r * cos(hoek), de y-coordinaat is y0
+
r * sin(hoek).
- Verbind de punten van de 2 cirkels. Zo bekom je een cilinder.
- Gebruik een shift-parameter s
om punt i van cirkel 1 met
punt i+s te verbinden. Dan
bekom je een koeltoren.
- Let op als de indexen buiten de array vallen (Invalid index
error)!
- Teken in een animatie kerncentrales met oplopende
shift-parameter:je s=0
(dan wordt er een cilinder getoond) - even wachten - s=1 tot s = NBR (je mag NBR heel hoog zetten)
S6: Hexagons
Maak een procedure die een hexagon in 2D tekent met gegeven
middelpunt en straal. Teken 1 hexagon in het midden van je scherm.
Start met .
2. Gebruik de procedure om een rij van
hexagons te tekenen.
- Tip: De
oneven
hexagons
liggen
R
x
sin
60º
hoger
dan
de
even
hexagons.
3. Optioneel: teken een 'stapel' van
hexagons.
H1: Kubus
Maak een procedure die een Kubus
tekent met gegeven
middelpunt,
de grootte S en de kleur.
Je kan bijvoorbeeld gebruik maken van de Rectangle procedure en Line procedure uit de gekende
Graph library.
H2: Toren bouwen.
Start met deze code en voeg je
procedure uit de vorige oefening toe.
We wensen een toren van 2.5m te bouwen door het opstapelen van
kubussen.
De onderste kubus heeft een ribbe van 1m, de volgende kubussen
zijn telkens 2/3 kleiner.
opgelet: als je 1m als CARDINAL
schrijft, in
centimeters bvb, dan geeft 2/3*... problemen,
immers wordt 2/3 = 0.666 afgerond tot 0
(is immers een cardinal). Beter doe je daarom ...*2/3.
Ambetante
Modula
Toch.
Stapel de kubussen opeen tot je toren net hoger is dan 2.5m.
tip: bereken telkens opnieuw de
'grond' voor de volgende kubus en de nieuwe grootte.
Teken de kubussen mbv de Kubus procedure van de vorige oefening.
Neem 1meter = 100 pixels. In de startcode hebben we de 'grond' op y=400
getekend.
Hoeveel kubussen heb je nodig? Print de waarde.
H3: Lopend Manneke.
Start met de code van
.
Gegeven is een procedure om een ledemaat te tekenen is gegeven
(parameters x,y zijn de coordinaten van het begin van de ledemaat, het
aanhechtingspunt aan het lijf).
Gevraagd:
- Teken een manneke met 2 benen.
- Zet deze code dan in een procedure om een manneke te tekenen
(eigenschappen: positie, grootte, hoek van
benen, kleur)
- Teken dan het manneke en laat het zich vooruit lopen door de
benen 'correct' te bewegen.
- Zorg dat het manneke links weer verschijnt als het rechts van het
scherm verdwijnt (let wel op dat je niet links buiten het scherm
tekent, voor negatieve waarden crasht je programma)
- Zorg dat je de snelheid van het manneke kan regelen:
- sneller als hij '+' indrukt, trager voor een '-'
- Gebruik:
- PROCEDURE KeyPressed():BOOLEAN;
Procedure geeft TRUE als er een toets werd ingedrukt. Deze procedure
blijft TRUE geven, zolang de ingedrukte toets niet uit de ‘inputbuffer’
gelezen wordt met de volgende procedure:
PROCEDURE RdKey(): CHAR;
Met deze procedure lees je een ingedrukte toets uit de inputbuffer. Als
de inputbuffer leeg is, wacht deze procedure tot er op een toets
gedrukt
wordt.
- Als het manneke aan het einde van het scherm komt, moet hij
terugkeren. Gebruik hiervoor de naarLinks boolean die de
richting van de voetjes aangeeft.
- Het programma moet stoppen als je op 'x' duwt.
Uitbreidingen: teken er
bewegende armpjes bij, laat hem springen als je op een bepaalde toets
drukt ...
H4: Ster tekenen
- Maak een procedure die een jodenster tekent met gegeven
middelpunt, grootte (zie S van de tekening) en de kleur.
De verhoudingen vind je terug in de tekening (waarbij sin(30 graden)/2
=
±1/4 en cos(30 graden)/2 = ±0.43)
Tip: om een cardinal met de reele constante 0.43 te
vermenigvuldigen, moet je deze naar een REAL omzetten. Dit kan je
omzeilen door de cardinal te vermenigvuldigen als volgt: *43/100.
Gebruik de graph-procedures Line (zie onderaan).
- Test de procedures uit door een ster in het
midden
van het scherm te tekenen.
X1: Bitmaps
Start with the code from
.
We defined:
- the type BitmapAr as two-dimensional arrays of
characters,
where each element represents a screen pixel.
- three bitmaps gHunter, gEuro &
gBackground
- a colormap (one-dimensional array) where each character is
mapped
on a color.
- a procedure CreateBitmaps() that fills all the
defined
arrays.
- Create the procedure DrawBitmap, that draws the bitmap
on
a certain postion on the screen, pixel by pixel with Plot(x,y,color).
Use
a
transparant
background
(the
'z').
- Change the procedure DrawBitmap, so that it draws the
bitmap
on a certain position on the screen, with a certain background color
and of a certain pixel size (use Rectangle instead of Plot).
These
are
extra
parameters.
- Create a new procedure SumBitmaps that creates a new
bitmap
that is the drawing of one bitmap on top of the other. Sum gEuro
on top of gBackground and draw the result.
T2: Output
- Wat is de output van het
volgende programma? Bereken het op
papier en bekijk het met de debugger. Je kan op de array klikken om de
inhouden van de elementen te zien.
- Let op voor de open array
in Proc2: de parameter arr
mag een array zijn van om het even welke grootte. De indexen van de
elementen van die array beginnen bij 0 en eindigen bij HIGH(arr).
MODULE T2;
<* NOOPTIMIZE + *>
FROM IO IMPORT RdChar, WrChar, WrStr, RdStr, WrLn, RdCard, WrCard,
RdInt, WrInt, RdReal, WrReal, RdBool, WrBool;
PROCEDURE Proc1(x, y, z: INTEGER): BOOLEAN;
BEGIN
x:= x + y + 1;
RETURN x > z;
END Proc1;
PROCEDURE Proc2(arr: ARRAY OF INTEGER): INTEGER;
VAR i: CARDINAL;
r: INTEGER;
BEGIN
FOR i := 0 TO HIGH(arr) DO
r := arr[i];
END;
RETURN r;
END Proc2;
VAR a:
INTEGER;
(*
variable-declarations
*)
d:ARRAY[2..4] OF INTEGER;
BEGIN
WrLn;
a := 1;
d[2] := 3;
d[3] := 4;
d[4] := 4;
WHILE Proc1(d[2], d[3], a) DO
a := Proc2(d);
DEC( d[3]); (* definition of
Decrement: DEC(n); is similar as n := n - 1; *)
INC( d[4]);
END;
WrStr("a = ");WrInt(a, 0); WrLn;
END T2.
T3: Scope
Schrijf tussen de haakjes (* .... *)
alle identifiers (procedures,
variabelen, types en constanten) die je op die lijn mag gebruiken.
MODULE T3;
FROM RealMath IMPORT pi;
PROCEDURE X();
CONST N=10;
VAR b: CARDINAL;
PROCEDURE Z();
CONST pi=3.15;
VAR c:CHAR;
BEGIN
(* ... *)
END Z;
BEGIN
(* ... *)
END X;
VAR c:CHAR;
BEGIN
(* ... *)
END T3.
T4: Var & Val
Wat
is de output van het volgende programma?
MODULE T4;
<* NOOPTIMIZE + *>
FROM IO IMPORT WrStr, WrChar,
WrCard, RdCard, WrLn, WrInt;
PROCEDURE Boe(VAR a:
CARDINAL; b: INTEGER);
BEGIN
b := b +
VAL(INTEGER, a);
a := a + 2;
END Boe;
VAR
x : CARDINAL;
y : INTEGER;
BEGIN
x := 6;
y:= 3;
Boe(x, y);
WrStr("x = ");WrCard(x,
0); WrLn;
WrStr("y = ");WrInt(y, 0);
WrLn;
END T4.
T4: Welke figuur?
Welke figuur wordt er met deze code getekend? Vind het zonder het
programma
te runnen
MODULE T3;
<* WOFF + *> <* NOOPTIMIZE + *>
FROM IO IMPORT WrStr, WrLn, RdCard, WrCard, RdInt, WrInt,
RdKey,
RdLn;
FROM Lib IMPORT Delay; (* Delay: let the program wait a
little
time *)
(* de graphics library vind je onder
C:/Bin/Xds/Def/Ts/Graph.def
*)
FROM Graph IMPORT Init, Rectangle, Circle, Line, Disc,
RawOutText;
FROM Graph IMPORT _clrBLACK, _clrBLUE, _clrGREEN, _clrCYAN,
_clrRED,
_clrMAGENTA;
FROM Graph IMPORT _clrBROWN, _clrWHITE, _clrGRAY,
_clrLIGHTBLUE,
_clrLIGHTGREEN;
FROM Graph IMPORT _clrLIGHTCYAN, _clrLIGHTRED,
_clrLIGHTMAGENTA,
_clrLIGHTYELLOW, _clrBRIGHTWHITE;
(*
deze
16
kleuren
zijn
constantes
gaande
van
0
tot
15
*)
PROCEDURE Asterisk(x0,y0,size,colour:CARDINAL);
(* Deze procedure tekent een ster met middelpunt x0, y0 en grootte size
*)
VAR a:CARDINAL;
BEGIN
a:= VAL(CARDINAL,((VAL(REAL,size)/(2.0))*0.7071) ); (*
cos(45)*)
Line(x0-size/2, y0, x0+size/2,y0, colour);
Line(x0, y0+size/2, x0, y0-size/2, colour);
Line(x0-a, y0+a, x0+a, y0-a, colour);
Line(x0+a, y0+a, x0-a, y0-a, colour);
END Asterisk;
PROCEDURE Triangle(x0,y0,size,colour:CARDINAL);
(* Deze procedure tekent een driehoek met middelpunt x0, y0 en
grootte size *)
VAR a:CARDINAL;
BEGIN
a:= VAL(CARDINAL,((VAL(REAL,size)/(2.0))*0.7071) ); (*
cos(45)*)
Line(x0, y0-a, x0-size/2, y0+a, colour);
Line(x0-size/2, y0+a, x0+size/2, y0+a, colour);
Line(x0, y0-a, x0+size/2, y0+a, colour);
END Triangle;
PROCEDURE RectangleExtra(x1, y1, breedte, hoogte, kleur:CARDINAL);
(* Deze procedure tekent een rechthoek met linkerbovenhoek x1,
y1 en gegeven breedte en hoogte
Met nog extra 'dingen' *)
BEGIN
Rectangle(x1, y1, x1+breedte, y1+hoogte, kleur,
FALSE); (* rechthoek met gegeven linkerboven- en rechterbenedenhoek *)
Triangle(x1, y1, breedte/4, kleur+1);
Triangle(x1+breedte, y1+hoogte, breedte/4,
kleur+2);
Asterisk(x1 , y1+hoogte, breedte/4,
kleur+3);
Asterisk(x1+breedte, y1, breedte/4, kleur+4);
END RectangleExtra;
VAR
x:CHAR;
BEGIN
(* Initialise graphics. Coordinatesystem: (0,0) is the top
left
corner *)
IF NOT Init(1, 1 , 600, 600) THEN (* creates a drawing
window
of 900 by 700 *)
WrStr("Sorry, graphics doesn't work");WrLn;
RETURN;
END;
(* Plot figures... *)
Circle(300, 300, 100, _clrWHITE);
(*circel met gegeven middelpunt en straal *)
Asterisk(300, 300, 40, _clrGREEN);
RectangleExtra (200, 200, 200, 200,
_clrRED);
(* Show graphics until user presses a key *)
WrStr("Press any key to finish the program");
x := RdKey();
WrLn; RdLn;
END T3.