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.
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?
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.
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).
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.