CS151 – Fall 2007: Programming Project 4

Due: Friday, October 19, 2007, 11:59:59:999 p.m. EST

 

In this project you will implement a class that allows people to interactively solve the cryptograms we created in Project 2.  To simplify things, the users of your class will do their solving in the terminal window.  Later on, perhaps for a final project, you can try to replace the terminal version with a nice graphical interface.  I will again give you a skeleton of the CryptogramSolver class and leave it to you to fill in the details to make it work.  Do not use any dialog boxes or other graphical elements.  All display and commands should take place in the terminal window and nowhere else.  Here is a very simple tester class.  Download my Cryptogram class from the course home page to use with your CryptogramSolver.  Feel free to add additional constructors, methods, etc. to it to help your testing, but we will test your solver using my Cryptogram class without your modifications.

 

CryptogramSolver Class

Please do not change the names of any public methods or instance variables (constants), or the order or type of any method parameters.  Doing so makes more work for the graders: bad for you and me.  You may change the name or type, or omit any private methods or instance variables.  You may also change the parameter names for any method to names more meaningful to you.  Add any additional private or public instance variables or methods you need to implement the methods specified in the skeleton.  Also add comments and @param and @return tags to support generation of web documentation for the methods and any public constants.

 

Additional Details:

1.        The class contains two instance variables both of type Cryptogram that I called puzzle and solution (you are free to change their names since they are private).  The puzzle is provided as a parameter to the class' single constructor.  The ciphertext of puzzle should contain the cryptogram to solve.  Either the puzzle's plaintext, i.e. the solution to the cryptogram or its key (used to produce the puzzle) or both may be empty strings or contain their values.  The solution's ciphertext is the same as puzzle's, i.e. the cryptogram to solve.  Solution's key is a record of the user's guesses about letter substitutions and corresponds to a decryption key.  Solution's plaintext field contains the result of encrypting solution.ciphertext with solution.key.  Note that this key is different from the key used to produce the ciphertext from the plaintext (which may or may not still be in puzzle.key).

 

2.        The class contains a single constructor that I have already written for you.  It takes a single Cryptogram object parameter and assigns it to the puzzle.  It also initializes the fields of the solution cryptogram.

 

3.        The public method solve() starts the interaction with the user and continues to run until the user indicates that he or she wishes to quit.  It should solicit a command from the user, process the command, and repeat this cycle until the user quits.  I suggest your solve() method call another method called processCommand() to decide what to do based on the user's command.  Solve uses the Scanner class which is described in Chapter 4.7 of your textbook to solicit keyboard input from the user via the terminal window.  The instance variable input is assigned a Scanner object to get input.  I suggest using commands that are characters or Strings, although integers are also a possibility.  For simplicity commands should be a single letter or number.  Remember that to compare int and char types you use ==, and to compare Strings you use the equals() method.  Use the appropriate Scanner method that corresponds to your choice of command codes:

a)    next(): is used to get the next String

b)    nextInt(): is used to get a int input

c)         to get a value of type char, use next() and then extract the character using charAt() or some other method

 

NOTE: solve() and display() described below are the only methods in your class that need to be public.  Of course, the constructor also needs to be public.  Any additional methods you create in the class should be private.  You shouldn't need to and it's not recommended, but if absolutely necessary you can make other methods public while testing and change them (don't forget to) to private when you are finished developing.

 

4.        For each command create/modify the constants I provided in the skeleton.  I used char for my commands, but you are free to change them to String or int depending on the command code choice you make.  Also, since the constants are private you are free to change their names to something more meaningful/descriptive.  At a minimum your solve method should support the following commands:

a)        display: show the user's partial solution and the cryptogram to solve (see below)

b)        quit

c)         give up: show the solution if one exists and the cryptogram in the format for display (see below), otherwise a message of some sort

d)        replace: substitute a single user-specified letter with another user-specified letter and then display

e)        reset: restores the solver to its original state (useful if the user makes mistakes, guesses the same letter multiple times, etc.) and display

Depending on where you perform these commands, use the following code to reset:
// set key back to alphabet and plaintext of solution

// back to cryptogram to solve

solution.setKey(Cryptogram.ALPHABET.toLowerCase());

 

// assuming solution's ciphertext has not been modified;

// if it has been use puzzle.getCiphertext() instead

solution.setPlaintext(solution.getCiphertext());

 

Whenever the user enters an invalid command, print a message in the terminal window telling them that their command was invalid and listing the valid commands.

 

5.        The private processCommand() method I suggest takes a single parameter which is the command the user entered.  Make sure the type of the parameter for processCommand() matches the type you chose for your commands and their constants.  Based on the command input by the user, the method should perform some actions.  I suggest creating some other private methods to handle each of these actions, rather than putting all the code in processCommand().  Hint think "if ... else" or switch.

 

6.        Letter replacement command.  Get a ciphertext letter to be replaced and the letter it should map to in the plaintext solution.  Think of this as one entry in the decryption key.  Once you get the letters from the user, call the private modifySolutionKey() method that I provide.  That method will record the user's guess in solultion.key.  You should then encrypt solution.ciphertext with solution.key using the static encryption method from my Cryptogram class and store the result in solution.plaintext.  Redisplay the modified solution for the user at the end of this process.

 

7.        The display() method should print in the terminal window the user's current solution along with the cryptogram in the following format.  Display both the current solution stored in solution.plaintext and the cryptogram being solved stored in puzzle.ciphertext in all upper case letters.  Each line of solution.plaintext (up to CHARS_PER_LINE characters long) should appear directly above puzzle.ciphertext with a blank line between successive lines.  Do not assume this constant will always be set to 80!  I will instruct the grader change it to another value for testing your class.  The following is an example of a correctly displayed session in progress (feel free to change the user command prompt text).

 

THIS IS A REOH, REOH, REOH FSYL STOIYL THAT IS QEAYT TS TEST THE AKIFITH TS

ZBDU DU A RJOH, RJOH, RJOH FSYL UZODYL ZBAZ DU QJAYZ ZS ZJUZ ZBJ AKDFDZH ZS

 

SVFIT AYN OEASSEQKFE A FSYL STOIYL SREO QXFTIVFE FIYES SC NISVFAH WITHSXT

UVFDZ AYN OJAUUJQKFJ A FSYL UZODYL SRJO QXFZDVFJ FDYJU SC NDUVFAH WDZBSXZ

 

SVFITTIYL WSONS.

UVFDZZDYL WSONU.

 

Please type a command (add list of commands here):

 

Requirements:

a)        No word should be broken across a line

b)        You should fit as many words as possible into each line.  Hint: keep adding words to a line until some condition occurs. 

 

Use the split method in the String class to help you do this.  For example, the commands

String plain = "it's a split test."

String[] plainWords = plain.split(" ");

for (int pos = 0; pos < plainWords.length; pos++)

          System.out.print(plainWords[pos]);

 

prints: it'sasplittest. to the terminal window, since each entry of plainWords consists of a word with the trailing space removed.  You need to add back the spaces between words when you construct the line.  Two long Strings are included in the skeleton to help test this method, but you should use your own long phrases too.

 

Arrays like Strings are indexed from 0.  In fact a String objects is implemented as an array of chars with some other instance fields that you can inspect in BlueJ.  To find the number of entries in an array the syntax is arrayName.length.  Note the lack of parenthesis (which annoys me to no end).  For arrays, length is an instance variable, not a method.  You can't change the length of an array once it's created.

 

8.        [Optional/extra credit choices]

a)    Modify the display method so that only characters that have been guessed by the user are displayed along with any punctuation from the ciphertext.  All other positions are empty spaces or blanks.

b)        Provide a method that gives the user a hint about letter to substitute.  If the key is set you can pick a random letter and give the user one of the letters from the key.  Alternatively and harder would be to give the user hint's based on single letters in the ciphertext (A or I), letters after apostrophes (T, S, D, LL), letter frequencies.

c)         Other ideas?

 

Strategy and Hints

First decide on your command type.  Get your user interaction working and for starters just print a message that says what action to take.  Then, implement a private method for each command.  Leave display for last: it is the hardest method and will take significant time to get working correctly. Once you get these methods working call then from processCommand when the user enters the appropriate command.  You may use a series of nested if else if ... statement or the switch statement to make your decisions.  You will also need to use while loops in several places.  Before trying to write the code for any method, try to work out what it is supposed to do on paper with some simple examples.

 

Start early and try to make a little progress each day.  Test early and often.  Sections 2.8, 3.6, and 5.5 of your book discuss different aspects of testing.  You can use BlueJ to test constructors and simple methods interactively.  Also, I think you will find the logging capabilities described in Advanced Topic 5.6 useful.  Whether you use logging or not is up to you.  If you do, be sure to turn it off when you submit your class file.  Make use of the online documentation, the lab TAs, your fellow classmates (to the extent allowed by the Collaboration Policy) and me early and often.  Don't put it off until the last minute.

Style and Documentation

All constructors, methods, and public instance variables should be commented using @param and @return tags to facilitate the generation of .html documentation similar to the Java Class Libraries on the Web via the Javadoc utility.  BlueJ automatically generates this documentation for your class when you switch from "Implementation" to "Interface" in the class editor window.  We've discussed the use of these tags in class and additional information is in section 3.3 of your textbook. 

 

Your code should adhere to the stylistic guidelines we have been discussing and which are in Appendix A of your textbook as much as possible.  In particular group different constructors, instance variables, and similar methods together.  Use meaningful variable names and internally comment your code liberally (with // or /*   */ pairs).

 

The graders will be instructed to determine approximately 10-15% of your project grade based on style, readability, and documentation.  Please use indentation, white space, and other stylistic techniques to make your code easier to read (and grade).

Project Submission

You will again submit your projects electronically.  To do so

1.        Connect to the Academics volume of the server called fileserver1.  From a Mac choose "Connect to Server ..." from the "Go" menu in the Finder, type afp://fileserver1 in the dialog box, and select Academics from the volume list.  From Windows machine open Windows Explorer, select "Map Network Drive" from the tools menu, pick a free drive letter and type \\fileserver1\Academics or just type it directly into the address filed.  When prompted for your user name and password, type COLBY\username, where username is your Colby username and enter your password.  These instructions are adapted from http://www.colby.edu/administration_cs/its/support/fileserver1.cfm. 

2.        On the Academics volume inside of the COMP/CS151 folder/directory you will see a folder with your Colby e-mail/login name and within that a private folder.  Copy into your private folder your CryptogramSolver.java file. DO NOT submit a .zip file, a project directory or any other files. DO NOT copy your entire project directory.  DO NOT submit a class that doesn't compile!  If you attempted some part of the extra credit please also include a brief proj3readme.txt file explaining what you tried and would like the graders to evaluate.

 

Acknowledgements