CPSC 124 Introduction to Programming Spring 2024

Lab 3
Making Choices

Due: Tue 2/13 at the start of lab


Introduction

This week's lab focuses on writing programs that involve making choices.

Collaboration

Labs and projects are for practice and learning. While it can be very productive to work on problems with your peers, it is also easy to underestimate how much you yourself understand and can do in such situations — so often something looks easy when someone else does it! With this in mind, you should always make the first attempt on a problem or programming task yourself using only the resources provided for the course (textbook, slides and examples posted on the schedule page, other resources linked on the course webpages). After that point, you are encouraged to come to office hours and/or go to Teaching Fellows. You may not collaboratively write solutions or code, and you may not copy solutions or code written by others, even if you contributed ideas.

You can discuss specific exercises with other students in general terms — such as how you might get started on that problem, or how or when to use various programming constructs, or strategies for debugging — but how to use a particular programming construct to solve a specific problem or debugging a particular program should only be discussed in office hours or with the Teaching Fellows.


Setup


A Note on Scanner

Many of the Scanner input routines are described as "scans the next token of the input as a ..." A token is just a string of characters. By default, Scanner uses whitespace to divide the input into tokens. For example, if the input is

  the  value of
    3 + 7
  is   10

the series of tokens would be the, value, of, 3, +, 7, is, 10.

Of importance is what happens to the whitespace itself. The whitespace is part of the input — space, tab, and newline are actual characters. (For example, if the variable s holds the value "Hello world!", s.length() would be 12 because the space between the two words is a character.) next(), nextInt(), nextDouble(), etc first skip over and consume any leading whitespace, then return (and consume) the next token. "Consuming" means that the character(s) are removed from the input and will not be read again. Note that this description does not mention the consumption of any trailing whitespace — whitespace immediately following a token is noticed (that's how Scanner knows it has found the end of the token) but it remains as part of the input until the next input operation.

Considering the example above, the first next() would read and return "the", leaving " value of\n  3 + 7\nis   10\n" unconsumed. (\n is a special symbol that denotes a newline. Note the final newline — this comes from the user pressing Enter when they have finished typing.) The second next() skips the leading whitespace (two spaces) and returns "value", leaving " of\n  3 + 7\nis   10" unconsumed. The third next() again skips the leading whitespace (one space) and returns "of", leaving "\n  3 + 7\nis   10" unconsumed. A subsequent nextInt() again skips the leading whitespace (the newline and two space) and returns 3, leaving " + 7\nis   10". And so forth...

nextLine() is a little different — it is described as "advances this scanner past the current line and returns the input that was skipped". This means that leading whitespace is not skipped, and that the newline that ends the line is consumed (but not part of the string returned).

Considering the example above, the first nextLine() would read "the value of\n", return "the value of", and leave "  3 + 7\nis   10\n". A second nextLine() would read "  3 + 7\n", return "  3 + 7", and leave "is   10\n". A third nextLine() would read "is 10\n", return "is   10", and leave nothing remaining in the input.

Where things can get a little tricky is when nextLine() is mixed with the other next routines. For example, consider an attempt to read the first line as three separate tokens and then the whole second line as a single line. It would seem that this would require three next()s followed by a nextLine(), but that's not quite right: the first next() returns "the", leaving " value of\n  3 + 7\nis    10\n"; the second next() returns "value", leaving " of\n  3 + 7\nis   10\n"; the third next() returns "of", leaving "\n  3 + 7\nis   10\n". The nextLine() "advances past the current line and returns the input that was skipped" — "past the current line" is just past the next newline in the input, which, since the newline at the end of the first line hasn't yet been consumed, is that newline. Thus nextLine() will return an empty string, leaving "  3 + 7\nis   10\n" remaining in the input. The correct solution is to include a second nextLine() to read the second line of input after the first nextLine() consumed the newline at the end of the first line. A common symptom if you forget is that the program will seem to skip past a prompt for input — because there is still a newline from the previous input remaining, nextLine() can complete right away instead of blocking until more is typed.


Exercises

Use the program development strategy introduced in last week's lab (constructing programs) and modeled in class:

For all exercises, utilize incremental development and employ good programming style. Also don't forget to autoformat your code and to include your name and a description of the program in each program!


Exercise #1

The program should get the hours worked per week and the hourly pay rate from the user, then print the user's total pay. If the user works more than 40 hours in a week, the time over 40 hours is paid at time and a half.

For example, if the user works 60 hours at $10/hour, the total pay should be $700 (40 hours at $10/hour and 20 hours at $15/hour).


Exercise #2


Exercise #3

In the casino game roulette, players place bets about where a ball will land on a spinning wheel. A single-zero (European) roulette wheel has 37 numbered pockets where the ball can land.

Your program should generate a random number between 0 and 36 (inclusive — both 0 and 36 should be possible numbers generated) to simulate spinning a roulette wheel, and then should print out where the ball landed (the number generated), the color of that pocket, and what bets are won. The output should look like the following:

  The ball landed on 17!

  The color of the pocket is black.

  You win on a low bet.
  You win on a black bet.
  You win on a second dozen bet.

Pocket colors:

Types of bets:

(There are many more bets than this possible in roulette, but your program only needs to consider these.)

Technical hints: exercise 2.2 at the end of chapter 2 in the text shows how to generate random integers in a particular range. Section 2.5.1 shows how to determine if a number is even or odd.


Exercise #4

The program should first ask whether the user wants water, juice, milk, coffee, or tea. Depending on the answer, the program should ask a follow-up question: for juice, whether the user wants orange, apple, or grape; for milk, whether the user wants regular or chocolate; and for coffee and tea, whether the user wants regular or decaf. Finally the program should print out what the user ordered.

For example: (user input is indicated with bold underline)

What do you want to drink?  (water, juice, milk, coffee, tea)  water
You ordered water.

A second example:

What do you want to drink?  (water, juice, milk, coffee, tea)  juice
What kind of juice would you like?  (orange, apple, grape)  apple
You ordered apple juice.

Your program should work no matter what case the user uses e.g. "juice", "Juice", "JUICE", and "jUiCe" should all be recognized as juice. Do this in an elegant way — you should not check every possible capitalization separately. (Hint: there's a String operation for this — see section 2.3.3 in the book.)

If the user enters an invalid choice of beverage (e.g. beer), the program should print "I don't know that beverage." If the user enters an invalid kind of beverage (e.g. tomato for the kind of juice), the program should print "I don't know that kind of juice." (or milk or coffee or tea) For example:

What do you want to drink?  (water, juice, milk, coffee, tea)  beer
I don't know that beverage.

Or:

What do you want to drink?  (water, juice, milk, coffee, tea)  juice
What kind of juice would you like?  (orange, apple, grape)  tomato
I don't know that kind of juice.

For extra credit, have the program also ask the user what size beverage is desired and include that when the drink order is printed. For example:

What do you want to drink?  (water, juice, milk, coffee, tea)  juice
What kind of juice would you like?  (orange, apple, grape)  apple
What size beverage do you want?  (small, medium, large)  small
You ordered a small apple juice.

If the user enters an invalid size, the program should print "I don't know that size."

The catch: To get the extra credit, your solution should be elegant — do not repeat the same code (such as asking the size of the beverage) in multiple places in your program. You should also have only a single System.out.println to print the whole line of output for the order (the "You ordered ..." line).


Handin and Grading

Don't forget to hand in your work when you are done!