CS 124, Spring 2021
Lab 2: Using Subroutines

Once again in this lab, you will be writing several small programs. However, there won't be any simple cutting-and-pasting of code. You will have to design programs that carry out the specified tasks. All of the programs use built-in subroutines in one way or another. In addition to subroutines you have already used (from System.out and from TextIO), you will be using some from the Math class and from String objects. And, as a bonus, this lab introduces JavaFX graphics. You'll learn some basic drawing subroutines, and you will use them to draw a simple picture.

This lab will be due by the end of the day next Tuesday, and it will be submitted using the program submission website, math.hws.edu/submit, as usual. It will also be accepted late until noon on Saturday, but starting with this lab, there will be a 10% penalty for labs that are turned in late without some good reason. You will be required to turn in programs named MathFunctions.java, TypingSpeed.java, MyName.java, and FirstGraphics.java.

Setup for JavaFX

Hopefully, you will have set up your Eclipse workspace to use JavaFX before coming to the lab. The procedure for doing so is given as the last two section of the Eclipse setup instructions,


If not, you will need to do it before you can work on Exercise 4. Note that you can work on the first three exercises without doing the JavaFX setup — but you really should try to make sure JavaFX is working before you leave lab.

You will need to have an Eclipse project that supports JavaFX, so you will have to create at least one new project for this lab. A project that supports JavaFX can also contain regular programs, so you can use the same project for all the exercises in this lab, but you will definitely need to create at least one new project, with JavaFX support.

The instructions tell you how to create a new "Installed JRE" that uses JavaFX. As explained in the next section of the instructions, when you create a JavaFX project, you need to make sure that that JRE is selected in the project selection dialog.

Once the project is created, you can download the program FirstGraphics.java, and add it to the src folder in your JavaFX project. If the setup for compiling JavaFX programs is correct, you won't see any errors in the program. If the setup for running JavaFX programs is also correct, you will also be able to run the program. If all that doesn't work, you should ask for help as soon as possible! Getting all the details correct in the JavaFX setup can be tricky!

Some Style Rules

Starting with this week's lab, your grade will be based partly on program style. When you write a program, it's important to follow rules of good programming style. These rules are mostly for human readers, not for the computer, and therefore the computer won't give you any feedback about them when you compile or run the program. So it's up to you to make sure that your programs show good style. Here are some of the rules that I expect all of your programs to follow:

Exercise 1: Some Math Functions

The Math class contains a variety of mathematical functions. As a short first exercise, you will write a program named MathFunctions that simply uses a few of those functions. This program has no input at all.

The function Math.random() gives a random number in the range 0.0 to 1.0. So, 100*Math.random() gives a random number in the range 0.0 to 100.0.

Your program should first make a random number in the range 0.0 to 100.0. It should then print out that number and the values of Math.ceil, Math.floor, and two other math functions applied to that same random number. The output of the program might look something like this:

A random number:         87.94480801002243
The next higher integer: 88.0
The next lower integer:  87.0
The square root:         9.37788931530024
The natural log:         4.476709436013197

The file for Exercise 1 must be named MathFunctions.java

Exercise 2: Timed Typing

For Exercises 2 and 3, you will need TextIO to do input. That means that it must be in your project. (It's not good enough to have it in a different project in the same Eclipse workspace.) You can copy-and-paste the entire textio package from one project in the Eclipse window into another project in the Eclipse window.

The function System.nanoTime() returns the number of nanoseconds that have elapsed since a certain time in the past. (When that certain time was is irrelevant.) A nanosecond is one one-billionth of a second. This function can be used to find the number of nanoseconds between two events in a program:

double startTime, endTime;
double elapsedTimeInSeconds;

startTime = System.nanoTime();
   .  // do something
endTime = System.nanoTime();

elapsedTimeInSeconds = ( endTime - startTime ) / 1000000000;

Write a program named TypingSpeed that lets the user type in a line of text and times how long it takes to type it. Then report the time, in seconds, and also report the number of characters per second that the user typed. A run of the program might look like this, where the user typed in the second line:

Type a line of text, and press return:
A man, a plan, a canal. Panama!
You typed 31 characters in 8.678162827 seconds.
That's 3.572184645297391 characters per second.

Remember that if you have a String variable, such as line for example, then line.length() is a function that tells how many characters are contained in the line.

The file for this exercise must be named TypingSpeed.java.

Exercise 3: Using String Manipulation Functions

We have seen that strings are objects and that they come with functions that operate on the string. All the functions that you need can be found in Section 2.3.3.

Write a program named MyName that gets the user's name and then does the calculations and shows the outputs specified below.

The program should ask for the user's full name (first name and last name, separated by a space). It should use TextIO.getln() to read the answer into a variable of type String. You should assume that the user enters a reasonable response. (If they don't, the program can crash, but that's OK—it's the user's fault, not yours.)

Once you have the user's name, use string functions to do the following computations with the string, and display the results (with appropriate labeling):

When the user runs the program, it should work more or less as follows, where the user in this example types in their name as "James Kirk":

Hi!  Please tell me your name.
Type in your first name and last name, separated by a space:  James Kirk

Your full name contains 10 characters
Your name in uppercase letters is JAMES KIRK
Your first name is James
Your last name is Kirk
Your initials are JK

Feel free to modify the format, but you should at least output the required information.

The file for Exercise 3 must be named MyName.java.

Exercise 4 Introduction to JavaFX Graphics

In the last part of the lab, you will get your first taste of GUI programming. At this point in the course, the only thing that you know how to do is to write a "once-through" list of instructions that is executed from beginning to end — but you can do anything with those instructions, as long as you have access to the right subroutines. In this part of the lab, you will use some drawing subroutines that are part of the "GUI toolkit" named JavaFX.

There is a lot about GUI programming that you won't understand for a while, such as how to open windows and respond to the user's actions. But as far as actually drawing on the screen, it all comes down to a bunch of subroutines for drawing basic geometric shapes. The program FirstGraphics.java has a very simple example of this. Your job for this exercise is to replace the drawing commands in that program with commands that will draw a picture of your own design.

The code that draws the picture is inside a subroutine definition named drawPicture, which looks like this:

public void drawPicture(GraphicsContext g) {
   .  // commands for drawing the picture

You should ignore everything outside that definition, since you won't understand it at this point. However, what you need to do inside that definition is simply write a list of commands for the computer to execute when the program is run, which is nothing new for you!

Drawing uses (x,y) coordinates, where x goes from zero on the left to some maximum value at the right, and y goes from zero at the top to some maximum value at the bottom. The coordinates can be real numbers, though in practice for this lab, you will probably use integer values for the coordinates. The maximum values for x and y in FirstGraphic.java are 800 and 600. (You can probably see how to change those values if you look through the code outside the drawPicture() subroutine.) The following illustration shows the picture that is drawn when FirstGraphics is run. The picture is in the white area. The numbers and arrows show how the coordinates work. Of course, you can compile and run the program to see the picture at full size.

You should understand how the code in FirstGraphics.java produced this picture before you try to make your own picture.

For the final exercise of the lab, you should modify FirstGraphics.java to draw a different picture. Erase the code inside the drawPicture() routine, and replace it with your own code. (To start, you might want to comment out the code instead of erasing it, so you will have it around for reference. Just enclose it between /* and */. But you should remove the old code before you turn in the program!)

Try to make a picture of some recognizable object, such as a house, a boat, a face, a clock, or a snowman. Maybe use a multicolor background made of two rectangles (representing ground and sky). Add some detail, like a cloud or some stars (stars could be asterisks, or maybe just little ovals). At a minimum, your picture should use at least a dozen commands and several different colors, and you should draw at least one String. Grade will be based partly on ambition and execution—and maybe a little bit on artistic merit, though I'm not really the one to judge that. (But I don't expect you to spend a huge amount of time on this. Some people in past classes may have gone a little overboard on similar exercises.)

You should replace the comments at the start of the program and before the definition of drawPicture() to describe what your program actually does.

The following subroutines are available for you to use in the drawPicture() routine:

  • g.setFill(c) is called to set the color to be used for filling shapes. The parameter, c is an object belonging to a class named Color. For example, if you want to fill shapes with red, you would say "g.setFill(Color.RED);" before drawing those shapes. The specified color is used for all subsequent fill operations up until the next time g.setFill() is called. Note that previously drawn shapes are not affected!
  • g.setStroke(c) is called to set the color to be used for stroking shapes. It works similarly to g.setFill(c).
  • g.setLineWidth(w) sets the size of the pen that will be used for subsequent stroke operations, where w is measured in pixels.
  • g.strokeLine(x1,y1,x2,y2) draws a line from the point with coordinates (x1,y1) to the point with coordinates (x2,y2). The width of the line is 1, unless a different line width has been set by calling g.setLineWidth(), and the color is black unless a different color has been set by calling g.setStroke().
  • g.strokeRect(x,y,w,h) draws the outline of a rectangle with vertical and horizontal sides. This subroutine draws the outline of the rectangle whose top-left corner is x pixels from the left edge of the drawing area and y pixels down from the top. The horizontal width of the rectangle is w pixels, and the vertical height is h pixels. Color and line width can be set by calling g.setStroke() and g.setLineWidth() some time before the rectangle is stroked.
  • g.fillRect(x,y,w,h) is similar to g.strokeRect() except that it fills in the inside of the rectangle instead of drawing an outline, and it uses the color set by g.setFill().
  • g.strokeOval(x,y,w,h) draws the outline of an oval. The oval just fits inside the rectangle that would be drawn by g.strokeRect(x,y,w,h). To get a circle, use the same values for w and for h.
  • g.fillOval(x,y,w,h) is similar to g.strokeOval() except that it fills in the inside of the oval instead of drawing an outline.
  • g.setFont( Font.font(N) ) sets the size of the font that will be used in subsequent calls to g.fillText() and g.strokeText(). The parameter N give the size of the font. (N is about the height of an upper case letter, in pixels.) The setFont method is actually more general than this, but this is the only way that we will use it for now.
  • g.fillText(str,x,y) draws the string str with its lower left corner at the point with coordinates (x,y).
  • g.strokeText(str,x,y) draws just the outlines of the characters in str with its lower left corner at the point with coordinates (x,y). This is only really useful if the font is fairly large.

There are many predefined colors for use as the "c" value in g.setFill(c) and g.setStroke(c), including Color.BLACK, Color.GRAY, Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.CYAN, Color.MAGNETA, and many fancier colors such as Color.FUCHSIA and Color.HONEYDEW. (You will see a list of them if you type "Color." in Eclipse). If you need even more colors, any color can be made from specific proportions of red, green, and blue. The proportions can be given by real numbers in the range 0.0 to 1.0. Here are some examples: Some examples:

g.setFill( Color.color(0.6, 0.3, 0) );   // brownish
g.setFill( Color.color(0.7, 1.0, 1.0) ); // light blue
g.setStroke( Color.color(0, 0.5, 0.5) ); // dark cyan

Most interesting, perhaps, is the idea of using Math.random() to specify some or all of the proportions:

g.setFill( Color.color( 0.0, Math.random(), Math.random() );  // a random green-blue

There are no predefined fonts, but it is easy to specify fonts of different sizes. For example:

g.setFont( Font.font(15) );   // A smallish font.
g.setFont( Font.font(36) );   // A rather big font.
g.setFont( Font.font(72) );   // A huge font.

The file that you turn in for Exercise 4 will be FirstGraphics.java.