Objectives

Students who complete this lab will demonstrate that they can:

Our problem in this lab exercise is to write an interactive song program that produces the the well-known (and over-sung) “Bottles of Beer” song:

99 bottles of beer on the wall, 99 bottles of beer. 
Take one down, pass it around, 98 bottles of beer on the wall.

98 bottles of beer on the wall, 98 bottles of beer. 
Take one down, pass it around, 97 bottles of beer on the wall.

...

1 bottle of beer on the wall, 1 bottle of beer. 
Take one down, pass it around, 0 bottles of beer on the wall.

0 bottles of beer on the wall, 0 bottles of beer. 
Go to the store and buy some more. 99 bottles of beer on the wall.

finis

There are two problems with singing this song: (1) We shouldn’t be singing songs that celebrate the over-consumption of anything, particularly alcohol; and (2) we shouldn’t be wasting our time and our voices singing pointless repetitive songs. A “solution” to these problems is to write an interactive program that allows the user to specify the number of verses, the container and the desired beverage/food. This would allow us to automatically create a “3 bags of chips” song, or a “10,000 barrels of monkeys” song.

Exercise 7.1
  1. Start up your IDE.
  2. Create a package
    edu.institution.username.lab07
    
  3. Create a program/class named ConsumptionSongConsoleDriver.

For graphical applications in Processing, we often started by sketching what our program should produce. With non-graphical applications, it’s still important to think about our goals for the program, but we must specify them in non-graphical ways. For example, a console-based interface to a configurable consumption song generator might look something like the following:

Please enter the following
    quantity: 3
   container: bag
   substance: chips
3 bags of chips on the wall, 3 bags of chips. Take one down, pass it around, 2 bags of chips on the wall.
2 bags of chips on the wall, 2 bags of chips. Take one down, pass it around, 1 bag of chips on the wall.
1 bag of chips on the wall, 1 bag of chips. Take one down, pass it around, 0 bags of chips on the wall.
0 bags of chips on the wall, 0 bags of chips. Go to the store and buy some more. 3 bags of chips on the wall.

finis

In this scenario, the user may choose any integer quantity, string container and substance. Note the control issues in the song:

To implement a program that addresses these issues, you’ll build a console-based Java application that handles the input and output and produces the songs. When you’re finished, you can exercise its functionality with the following test “songs”:

If the application can handle these test cases properly, you can be reasonably confident in its capabilities.

The Console-Based Interface

You’ll start implementing this application by building its console-based user interface. To simplify matters, you’ll postpone implementing the actual lyrics of the song until the next section.

Exercise 7.2

Write a main() driver method in the ConsumptionSongConsoleDriver class that implements this algorithm:

  1. Print a prompt for and read the number of verses (e.g., 3) from the keyboard.
  2. Print a prompt for and read the container name (e.g., bag) from the keyboard.
  3. Print a prompt for and read the substance name (e.g., chips) from the keyboard.
  4. Print the lyrics of a consumption song with the appropriate number of verses, container and substance.
  5. Print a closing message.

As you do this, note the following things:

You’ll add the song lyrics in the next section.

The Make-Song Method

With your console driver in hand, you can turn to the (more interesting) makeSong() method. You’ll implement this in a couple of iterations.

As a way to get started, it is often a good idea to write a stub version of a method before implementing its complete functionality. The stub declares and empty version of the method and invokes it appropriately, which allows you to verify the method signature before embarking on the full definition of the method’s functionality.

Exercise 7.3

Implement a stub version of makeSong() as a sibling method to main() inside the ConsumptionSongConsoleDriver class. Use the following algorithm:

  1. Receive quantity, container and substance.
  2. Set result = "", an empty string.
  3. Return the result string.

Obviously, something interesting will eventually happen between steps 2 & 3, but for now implement just this much and include the method invocation in main() in the appropriate place (i.e., step 4 of the algorithm in exercise 7.2). Because makeSong() returns a string, step 4 of main() should invoke makeSong() and print the result. The program should run without error and print a song with no lyrics.

With the stub in place, you can move on to the core functionality of the method.

Exercise 7.4

Extend your makeSong() implementation to include the core functionality, specified in the new step 3 shown in this augmented algorithm:

  1. Receive quantity, container and substance.
  2. Initialize the result string to "", an empty string.
  3. For each valuecount in the range quantity down to 0:
    1. Concatenate the following onto the end of result:
      count + “ ” + container + “s of ” + substance + “ on the wall, ” + count + container + “s of ” + substance + “.” +
      “ Take one down, pass it around. ” + (count - 1) + " " + container + “s ” + “ of ” + substance + “ on the wall.\n”
    End loop.
  4. Return the result string.

Here, steps 1, 2 & 4 are repeated, though perhaps renumbered, from the previous version of the algorithm. When this implementation is finished, run it on your test cases.

Your implementation should work on the “0 pieces of eight” and “-1 lumps of coal” test cases, but the “3 bags of chips”) is likely to behave something like this:

Please enter the following
    quantity: 3
   container: bag
   substance: chips
3 bags of chips on the wall, 3 bags of chips. Take one down, pass it around, 2 bags of chips on the wall.
2 bags of chips on the wall, 2 bags of chips. Take one down, pass it around, 1 bags of chips on the wall.
1 bags of chips on the wall, 1 bags of chips. Take one down, pass it around, 0 bags of chips on the wall.
0 bags of chips on the wall, 0 bags of chips. Take one down, pass it around, -1 bags of chips on the wall.

finis

You’ll deal with the grammatical and lyrical errors in the last couple of verses in the next section.

Adding selective behavior to the makeSong() Method

In this section, you’ll fix two problems with the algorithm. First, the last verse should read as follows:

0 bags of chips on the wall, 0 bags of chips. Go to the store and buy some more. 3 bags of chips on the wall.

This version should be handled as a special case because it’s unlike the other versions.

Exercise 7.5

Extend your makeSong() implementation to handle the last verse properly, as specified in the modified contatenation operation shown in step 3 of this augmented algorithm:

  1. Receive quantity, container and substance.
  2. Initialize the result string to "", an empty string.
  3. For each value count in the range quantity down to 0:
    1. Concatenate the following onto the song string:
      count
      + “ ” + container + “s of ” + substance + “ on the wall, ” + count + container + “s of ” + substance + “.” +
    2. If we are not on the last verse:
      1. Concatenate the following onto the song string:
        “ Take one down, pass it around. ” + (count - 1) + container + “s”
      otherwise:
      1. Concatenate the following onto the song string:
        “ Go to the store and buy some more. ” + quantity + " " + container + “s”
    3. Concatenate the following onto the song string:
      “ of ” + substance + “ on the wall.\n”
    End loop.
  4. Return the result string.

When this implementation is finished, run it on your test cases.

One last problem one can see in this output is the pluralization of the container word. The algorithm should generally add the “s” to the container to make it plural but when the count is 1, no “s” should be added (e.g., “1 bag of chips”).

One rather simple way to fix this problem would be to add another if statement that adds the “s” only when count!=1 . The problem with this solution is that you’d have to write a new if statement each time the container is expressed, which for this method would require four identical if statements. This would not be a good approach because it would make the code harder to understand and harder to maintain.

A better way to solve the problem is to “factor out” this pluralization function into a separate method that receives a word and the number and returns the appropriate string. We could use this new function as follows:

song += count + " " + pluralize(container, count) + " of ";

This method should receive a word and a number, and return a pluralized version of the word if the number is not 1. For example, if the word is “bag” and the number is 1, then the method should return“bag”, otherwise it should return “bags”. The method will assume that the word is a noun in singular form with regular pluralization rules.

Exercise 7.6:

Address the pluralization problem by doing the following:

  1. Design and implement a new pluralize() method that implements the behavior just described. We haven’t given you an algorithm for this method, but you’ll find that it’s a rather straightforward use of the two-branch-if-statement pattern shown above.
  2. Add an invocation of pluralize() in each situation where the container is included in the song string.

The resulting program should handle all the test cases properly.

Your lab solution now integrates all the basic control structures (sequence, selection, repetition) and methods in a Java application.

Checking In

Submit all the code and supporting files for the exercises in this lab. We will grade this exercise according to the following criteria: