Program 3

Programming with Classes

Informatics Core II
INF-42


Introduction Please print a copy of this assignment, read it carefully, and highlight material you think will be useful to you while you are working on the program or submitting it.

This programming assignment is designed to ensure that you know how to write programs that use constructors, methods, and fields (although rarely) in other classes. Of course, you will continue gaining experience with the standard control structures in Java (blocks, ifs, fors, breaks, try/catch) as well as the more basic Java features (declarations and expression statements using arithmetic, state-change, relational, and logical operators).

You will write three programs in this assignment. As always, you can check the behavior of your programs against mine by downloading, unzipping, and then running the file Program #3 Executables, to help you understand the specification of the problem and observe the programmer/user interaction that you are to implement. See Program #1 for details on how to run these executables on both PCs and in Eclipse (PCs and Macs). Remember, you can run these programs, but not examine their source (Java) code. Copy the input/output form of the executable programs in the programs that you write: use exactly the same prompts and messages.

For your information, I am listing below the number of lines in my solution programs. These programs are formated in the standard way. I am counting only lines with code (even if the only code on the line is a brace that closes a block); but I am not counting blank lines norlines filled with comments. My "big collatz" program is 24 lines; my "dice ewar" program is 72 lines; my "phone database" program is 37 lines. Your programs might be smaller, and they might be larger; but if your program starts going over 2-3 times the size of mine, you might want to rethink it (or come get some help).

Please follow the instructions below for each program: finish each enhancement before continuing to the next one (including printing whatever messages it displays in the console, copied exactly).

The Class Examples program illustrates the use of many classes, including the ones that you will need to use in this assignment. The last two programs require writing nested loops: one loop inside another. I used multiple break statements inside some of these loops.

To work on this assignment, create one Java project (call it Program3) and create three new Java classes in it (as you did in Program #2). Each class will contain a program that you will write to solve one problem; name the classes BigCollatz, DiceWar, and PhoneDatabase. Write, run, and debug each class/program as you did in Program #2. When you finish each part, submit its .java file.

Only one programmer of the pair should dropoff the programs: the same one for each part. It doesn't matter which of the pair submits, but that person should submit all the parts. Of course, each program should contain both student names (in the comment: the same one you cut, pasted, ane filled in at the top of each program in Program #1).


Collatz with BigInteger Don't start this project with the new project folder. Instead, download the Program3 project folder, unzip it, and start a new project in Eclipse using this project folder (which contains a Collatz.java program that works for int values). Later, create the DiceWar and PhoneDatabase classes here.

When compiled and run, the Collatz.java class prompts the user for an int value and performs the Collatz process (read the comments for all the details) on that number until it is "reduced" to 1. We have seen this program before, when working with the Eclipse Debugger.

This program requires you to use objects constructed from the BigInteger class; remember to import it.

For this programming assignment, enhance this program to use variables that refer to BigInteger objects rather than store int primitives. In this way, there is almost no limit on the size of number that we can apply the Collatz process to, checking whether all values are ultimately reduced to 1 (which happens for all examples I've tried, and happens very quickly).

Fundamentally what you are doing in this program is translating from the use of primitive types and values to the use of reference types and objects. This is a good starting point for switching to object-oriented programming. It will involve importing the BigInteger class (see Javadoc for its full name, including its package). In addition, you should...

  • Use constructors for BigInteger objects to initialize variables/constants, instead of using int literals -there are no BigInteger literals! Also note that the BigInteger class declares some public final constants which you should find useful. Remember that the constructor for BigInteger takes a String argument, that is filled with digits.
  • Use methods like .divide, .multiply, and .add to perform arithmetic on BigInteger values (instead of using arithmetic operators -they do not work for BigInteger values). For every int operator, there is a similar BigInteger method (check the Javadoc). Note that there are no state-change operators for BigInteger objects (e.g., no ++): like String, it is an immutable class.
  • Use methods like .equals and/or .compareTo to compare BigInteger values (instead of using relational operators: remember that == probably doesn't do what you want done!)
Check the Prompt class for a useful input method. You should also make good use of cascaded method calls in your solution (taking the place of subexpressions and operator precendence).

Submit your final program (test it on small numbers, and big numbers: numbers with tens or hundreds of digits). Finally, remember to update the Description: comment to describe the changes added to the program.

PS: With a perfect understanding of BigInteger converting this program would take about 5 minutes: I guess you will take longer, because you will learn a lot about the BigInteger class, specifically, and understanding how to use objects, generally.


Dice War This program requires you to use objects constructed from the DiceEnsemble and Timer classes; remember to import them. Write a program that simulates playing games of dice war; the program should also collect certain statistics while it is playing these games and report them after the required number of games have been played. In a game of dice war, each player starts out with his/her own dice ensemble, consisting of (2,6-sided) dice, and some number (entered by the user) of chips. Each player roles his/her dice. If one player's pip sum is higher, that player gets a chip from the other player. Whenever one player has no chips left, the game is over (and that player has lost; and the other player has won). So there are many plays (throws of the dice) in each game.

Your program must prompt the user for the number of games to play, and the number of chips with which the players start each game. It also prompts the user to determine if the program's behavior is to be traced (use tracing as a debugging technique, only when playing few games). The program then simulates that many games of dice war, using objects constructed from the DiceEnsemble class: one pair of dice for each player. It keeps track of the number of times each player wins, the length (number of dice rolls) of the shortest and longest games, and the total number of dice rolls (over all the games). It also uses a Timer to keep track of how long (in clock-time) it takes to play all the games. Try to use the DiceEnsemble objects themselves to keep track of some of the required information, so you do not have to declare extra variables.

Ultimately the program prints

  • how often each player won (it is a fair game, so these numbers should be about equal)
  • the length of the shortest and longest games
  • the total number of rolls (over all games)
  • the average number of rolls per game
  • the amount of time it took to simulate all the games
  • the simulation speed (number of games per second)
Finally, the program should also be capable of tracing its events. Such a facility is not used for long simulations, but instead it is very useful for short debugging runs. By tracing every important event in the simulation, we can display information useful for spotting bugs. When you build your program, you should trace the following events (if the user requests a trace)
  • starting a new game
  • playing one roll: indicate what each player rolled and how many chips each player has left after the roll (and redistribution of the chips).
  • winning a game
Run my executable with tracing (for a small number of games), with each person starting out with 3-5 chips) and without tracing (for a large number of games, with increasing number of starting chips) to observe all its behavior.

Note: DO NOT write the tracing code by writing one big if that determines whether or not to trace, and then having two copies of the program controlled by the if: one with tracing and one without. Instead, write one copy of the program that uses multiple ifs in it to decide whether or not to trace aspects of that one program.

For this assignment, try to work out your own enhancements. A starting point could be writing a program to play one game (with the user supplying the number of starting chips); then add tracing; then add playing multiple games (with the user supplying the number); then add code for keeping all the statistics; then add timing the game. Explore the Javadoc of the DiceEnsemble and Timer classes, and use them effectively to minimize the variables and code you must write. I found Integer.MAX_VALUE (check out this static final field in the Integer wrapper class in Javadoc) useful as an initialization for computing the smallest-length game, although there are many other ways to compute this value correctly.


Phone Database This program requires you to use objects constructed from the TypedBufferReader and StringTokenizer classes (as well as use of the EOFException class); remember to import them.

Write a program that reads a database of names and their associated phone numbers (from a file, catenating them into one huge String). As a debugging check (leave it in your program; it is in my executable too), ask the user if he/she wants to print the database (to see if it has been read correctly); if so, print the String. Then, it repeatedly prompts the user for a name (again, a String) and look up and print its associated phone number (or print that the name cannot be found) in the database. If the user enter the "name" QUIT, whether upper-, lower-, or mixed-case, the program should instead terminate.

Your program must prompt the user for an input file (see the file phoneinput.txt provided with the executable) and then read all the names and phone numbers from that file (each is read as a String) from that file, catenating them into one large database string (with a space between every name and phone number).

I want you to write a loop that executre a try-catch to input all these values one at a time, terminating when the EOFException is thrown. You MAY NOT use the readAllTokens method in the TypedBufferReader class to read the input; well.

Then your program should repeatedly prompt the user for a name, and terminate if the user enters QUIT; if the user enters any other name, use a loop to process a StringTokenizer object (initialized to the database): it should process tokens until the name is found (use a case-insensitive equality comparison; then the next token is the phone number) or there are no more tokens (then the name was not in the database).

Note hat if you enter a name in the database the program should print the number directly following it; if you enter a telephone number in the database it should print the same "not found" information as an unfound name. Run my executable to see what it does.

Note that the Class Examples program illustrates how to read all the values from a file, and how to process all the tokens in a String; study this code and adapt it to this program. This resulting program is pretty small; it requires file reading (see above), and ensures that you understand how to use the StringTokenizer class (which has a constructor and a few useful methods that you must learn to use).


Extra Credit The dice war problem has 1 point of extra credit. To earn it, at the bottom of the main comment in the DiceWar class, include a section labelled Extra Credit. In this section, estimate the average number of dice rolls for a game where each player starts out with 1,000,000 chips. Explain the details of how you arrived at your estimate.

Do not discuss your estimate with anyone but the student you are pairing with.