Description
The purpose of this lab is to ensure that you are confident with – and have had
a lot of practice at – writing small clear functions that give precise control over
repetitive tasks. The lab is divided into three almost independent sections. Be
careful that you don’t ruin the work you did for one section while you are
working on the next.
Section A – Conversions
A1. Remembering how to start
Remind yourself of how to write the most basic repetitive function of all, one that
takes two parameters, A and B, and just prints all the numbers from A to B inclusive.
This will be the starting point for everything this week, so type it in, and make
absolutely sure that you have got it right, and it really works.
A2. Exotic Canada
You could adapt that function to count differently. Make a new version of it that
counts in steps of five, so that if you said “numbers(10, 90);” in main, your
program would print 10 15 20 25 30 … 85 90. Test it, make sure you got it
right.
Now imagine that you are taking a trip to some wild and exotic part of the world
where they use the metric system. Canada perhaps. You’ll be driving, and don’t want
to get a ticket for going too slow, so you want a conversion table to translate miles per
hour into kilometres per hour. One mile is 1.609344 km.
Adapt your function so that it doesn’t just print numbers, but prints mph to kph
conversions instead. Where it used to print X, it should now print X mph is Y kph.
The first few lines of output would look something like this
10 mph is 16 kph.
15 mph is 24 kph.
20 mph is 32 kph.
25 mph is 40 kph.
But there’s a complication. You will also be visiting the Mayor of Toronto, and he
likes to measure speed in miles per minute (not grams as you may have thought). So
what you need is a three way conversion like this.
10 mph is 16 kph or 0.17 mpm.
15 mph is 24 kph or 0.25 mpm.
20 mph is 32 kph or 0.33 mpm.
25 mph is 40 kph or 0.42 mpm.
You are probably seeing some ugly output now, with lots of distracting extra
digits. When a program calculates (for example) 10*1.609344, it gets a very
accurate result, 16.093444). Usually, precision is what you want, but in this case it
doesn’t help. To throw away all the digits after the decimal point, and reduce the
value to an int, the C++ expression is
(int)(10*1.609344)
Yes, you do need all those brackets, and of course it works for all numbers with
decimal points in them, not just 10*1.609344. It is even better if you round the
result to the nearest int. The trick for that is
(int)(10*1.609344 + 0.5)
which works for all positive values.
But that makes sense only for kilometres per hour. Kilometres are close enough to
miles that we don’t want to see any digits after the decimal point. Miles per minute
are another thing altogether. We want exactly two digits after the point. You can
probably work out how to reach that goal.
Section B – ASCII Art
B1. Stars
Go back to your basic counting function from A1, and this time adapt and adopt it in
a different way. Make a function that has one parameter N, which just prints a row of
N stars. That’s it, nothing complicated, stars(7) should just print “*******”.
Your function in A1 had two parameters, but this time we want a function that has
only one parameter.
B2. Dots
Now make another function almost identical to that, but it should print dots instead of
stars. dots(7) should just print “…….”. How are you going to test it? If you
just print spaces, you don’t see anything.
B3. Dots and Spaces
Now make another function that takes two parameters A and B, and prints A dots
followed by B stars followed by A dots followed by a new line. dotssstars(3,
4) should just print “…****…”. Remember that having functions that use
other functions to do most of their work is a good design technique.
B4. Another adaptation
Thinking about how you controlled repetition so far, write yet another function that
takes two parameters A and B. This one should count down from A to 1, and at the
same time count up from B in steps of 2. That sounds pointlessly complicated, but
one little example will make it clear: sequence(5, 1) should print
5 1
4 3
3 5
2 7
1 9
B5. Combining
Still remembering the idea of little functions using other little functions to do their
jobs, write another function just like sequence, except that it doesn’t print the
numbers, it uses them as parameters to dotssstars. This new function will draw
triangles: as an example triangle(5, 1) should print
….*….
…***…
..*****..
.*******.
*********
Not very spectacular I admit, but it’s all good practice.
Section C – Circles
C1. A circle
One way to draw an approximate circle is to draw a straight line a short distance, then
turn a small amount to the right. Repeat that so many times that all the turns add up to
360 degrees, and you’ll be back at the starting point. If the steps are small enough,
nobody will be able to tell the difference between that and an exact circle. Computer
monitors aren’t really very sharp, so the steps don’t need to be really really small, just
small.
Do it. Write a function that draws a circle. You should be able to control the size of
the circle by altering its parameters.
This is how you get the most accurate value for pi in C++:
const double pi = acos(-1.0);
C2. Weaponising
Now your circle is going to be the wheel of a cannon.
Given the position of the bottom of the wheel and the
aiming angle (x, y, a), you should be able to make a simple
cannon anywhere, aiming at any angle you want, such as 30
degrees (from vertical, shown to the left) or 75 degrees
(below).
If you need some help with to get the shape right, there are some formulas on the next pages.
That’s the END of the lab. The rest is just if you need a bit of help with the shape:
This is the cannon sitting on a wheel. The wheel’s radius is r.
a is the aiming angle.
L1 is the distance from the back of the cannon to the wheel’s axle, L2 is the rest of the
length.
Like all cannons it is wider at the back (w1) than the front (w2).
G is the point on the ground where the wheel rests. Its coordinates are (xg, yg).
C is the exact position of the axle, its coordinates are (xc, yc).
P is the easiest point to start drawing the body of the cannon from, coordinates (xp, yp).
E is the point where the ball pops out when it is fired, coordinates (xe, ye).
This is a simplified picture of the body of the cannon shown with its “bounding box”.
The point is to illustrate the difference between the real length of the cannon (len) and
the sum L1+L2.
The angle shown as b is also helpful when drawing the shape. When the cannon is
aimed at angle a, the heading for the bottom line is (a-b). Don’t forget that all angles are
computed in radians.
xc = xg
yc = yg – r
b = asin((w1-w2)/2/(L1+L2))
xp = xc – L1 * sin(a-b)
yp = yc + L1 * cos(a-b)
len = (L1+L2) * cos(b)
Finally, to find the point E, we need two extra values:
d is the distance between points P and E
g is the angle from point P to point E if the cannon lies flat as in the third diagram.
d = sqrt(len*len + w1*w1/4)
g = asin(w1/2/d)
xe = xp + d * sin(a-g)
ye = yp – d * cos(a-g)