Due: Friday, September 28, 11:59:59:999 EST
In this project you will gain more experience with defining your own
classes. You will specify both the
public interfaces and the implementation behind those interfaces.
To practice your specification and implementation skills, you will create a
class that models a kind of word puzzle called a cryptogram. Cryptograms are single letter
substitution ciphers or codes. For
example,
"L DP KHUH, DQG BRX
DUH WKHUH."
is a cryptogram of the phrase
"I am here, and you
are there."
The substitution scheme used in the above example is
called a Caesar Shift: every letter of he message is replaced with the third
letter after it in the alphabet.
However, cryptograms need not employ such regular substitutions. The choice of letters to substitute can
be completely random and has no effect on the difficulty of the resulting
cryptogram. One of the things your
class will do is generate a key that produces such a random cryptogram.
One solves cryptograms using properties of the
English language such as letter frequencies, punctuation marks, etc. You can usually tell if you have the
correct answer because it should make sense as an English phrase. You can find daily cryptograms in
some newspapers and on a variety of web sites. On these web sites they also sometimes have cryptogram
solver applications. The
applications don't solve the puzzle, rather they facilitate the interactive
solving process.
Create a project called username-proj2, where username is your login/email address, e.g.
srussell-proj2. In that project
create a class called Cryptogram.
Please do not deviate from these naming conventions, since it makes more
work for the grader and cranky graders aren't a good thing for you or me. Your Cryptogram class will model and
produce cryptograms. You can then torture friends, family, one another, and me
with the puzzles you produce.
Recall, that each class consists of constructors,
methods, and instance field/variables.
Constructors describe how to create a new object or instance of the
class, methods are actions that objects of the class can perform, and instance
fields/variables store information specific to each object or instance of the
class.
Your class should have:
1.
Three private instance fields in your class, all strings: one
for the plaintext, one for the ciphertext, and one for the key. What you call them is up to you since
users of your class will access them with get and set methods (see below).
2.
Three constructors
a)
one that takes no parameters and creates a "blank"
cryptogram
b)
one that takes a single parameter: a plaintext string and
creates a cryptogram instance with that plaintext
c)
one that takes two parameters: a plaintext string and a key string,
and creates a cryptogram instance with the specified plaintext and key string
(again for ease of testing please make plaintext the first argument and the key
the second parameter)
3.
Three get methods all of which take no parameters and return a
String.
a) getPlaintext
b) getKey
c)
getCiphertext
(return an upper case String, i.e. all capitals).
4.
Three set methods all of which take a single String parameter
and return nothing.
a) setPlaintext
b) setKey
c)
setCiphertext
5.
[Strongly suggested but not mandatory]
a)
A public class constant of type String using the syntax
public static final String ALPHABET =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
b)
An public class constant of type int using the syntax
public static final int ALPHABET_SIZE =
ALPHABET.length();
(why is this preferable to explicitly setting it to 26?)
These two things will appear
multiple times in your methods and are fixed across all instances of the class
you create. Hence, it's good
practice to make them class constants (like the Calendar class constants we
used in the last project). Doing
this also makes your code more readable. See section 4.2 of your textbook for a
discussion of constants and the syntax used to declare them (focus on the
"In a class" variety).
We will talk more about constants soon.
6.
A method called encrypt
that takes two parameters: the first a String is a plaintext, and the second
also a String is a key (again, please don't change the order of the
arguments). The method should also
return a String. It should create
a cryptogram (also called a ciphertext) using the plaintext and key parameters.
To encrypt, you replace all instances of
"A" or "a" in the plaintext with the first letter of the
key, all instances of "B" or "b" with the second letter of
the key, and so on. Rather than
writing a statement to explicitly search and replace each letter of the
alphabet, you should use "for loop". We haven't discussed them yet, but I will talk about them
enough for you to use them in the project. You can also look ahead in the book for information. The following code snippet assumes you
defined the suggested constants and is an example of a "for loop" in
action:
//prints every letter of the alphabet on a separate
line
String myAlphabet =
Cryptogram.ALPHABET;
for (int index = 0;
index < 26; index++)
{
System.out.println(myAlphabet.charAt(index));
}
(It would be better to use ALPHABET_SIZE instead of 26, but I
didn't want to make the example more confusing.) The loop counts from 0 to 26 and stores the value in
variable called index that only exists inside the body of the loop, denoted by
{}. Each time the test index<26
is performed, and if true, the body of the loop (it can be more than one
statement) is executed after which index is incremented by 1 and the process is
repeated. The shorthand index++ is equivalent to index=index+1. You can change the lower bound, 0, the
upper bound, 26, or the < sign to other things if you want, but you
shouldn't need to.
String methods you will probably want to use in the encrypt (and decrypt and generateRandomKey methods too)
include: substring(), replaceAll(), toUpperCase(), toLowerCase(), length(),
replaceFirst(), split(). You may
not need all of these, and you may use any String methods not in this list. No classes other than String and Random
are needed to implement the required functionality.
7.
A method called generateRandomKey
that takes no parameters and outputs a random key in the form of a String. Again, a key is a string of 26 letters
(preferably upper case) with each letter appearing exactly once.
8.
[Optional/extra credit choices]
a)
A method called decrypt
that takes two parameters: the first a String is a ciphertext, and the second
also a String is a key (again, please don't change the order of the
arguments). The method returns a
plaintext "guess" by applying the key to the ciphertext. Note that key used to encrypt is
different from the key used to decrypt.
b)
Try to figure out how to convert an encryption key into a
decryption key and write a method called ecryptionToDecryptionKey that does
this. It takes a single String parameter representing an encryption key and
returns a String which is the decryption key.
c)
Modify the constructor that takes two parameters to also
encrypt the plaintext parameter using the key parameter and assign the result
to the object's ciphertext instance variable.
d)
Other useful or fun extensions.
First implement the get and set methods and constructors and make sure they
work before moving on to the more challenging encode method.
No additional classes are needed to implement the encode method other than the String
class methods. Before trying to
write the code, try to work out an algorithm for encoding on a piece of
paper. First, understand what you
want to do, then figure out how to accomplish it. There is a small issue you will have to deal with. Suppose your key starts with BA so that
A gets replaced with B, B with A, and Y with I. For the plaintext of BABY, make
sure your encrypt
algorithm outputs ABAI and not AAAI.
I may give hints if this proves too difficult. If you figure it out DO NOT tell anyone else. Help them to come up with the solution
themselves. Once you get encrypt working, then decrypt should be easy: just reverse
the process.
Leave generateRandomKey
for last. I may make this method
extra credit, rather than required depending on how people do. You can test your encrypt method using the sample keys
provided below or generate your own key by hand. Remember, the key is just a string with each letter of the
alphabet appearing exactly once.
Start early and try to make a little progress each day. Test early and often. You can test interactively with BlueJ
or write a CryptogramTester class to help with testing. Make use of the online documentation,
TAs, and me. 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. Try to use meaningful variable names and
internally comment your code liberally (with // or /* */ pairs).
For simplicity we will treat our keys as strings of 26 letters. This will allow us to implement all the
desired functionality using methods from the String class. So, using Key 1, A is replace by D, B
by E, and so on. No substitution
is performed for punctuation marks or spaces. Key 1 is the key used to produce the example described at
the beginning of this project description. Key 3 is randomly generated.
Plaintext: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Key 1: DEFGHIJKLMNOPQRSTUVWXYZABC
Key 2: ZYXWVUTSRQPONMLKJIHGFEDCBA
Key 3: BGQEOCPHTFXWJSKUDRNMALYIZV
Please remove any additional classes you create while working on the project
for testing before you submit your final solution. However, if you create a CryptogramTester class feel free to
submit the source (.java file) for it.
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. 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.
NOTE: At this time only Mac (afp:
) connections are possible.
2.
On the Academics volume inside of the COMP/CS151
folder/directory you will see a folder with your Colby e-mail/login name. Copy your Cryptogram.java file from
your project directory to that folder.
If you have want to submit other classes, copy the .java files for those
classes too. Also, please include a
brief readme.txt file explaining the additional classes and how to use them.
By convention, cryptograms are printed in capital letters which are easier
to read and double-spaced so that you can pencil in your solution above the
puzzle. Single letters,
punctuation, words with special patters, etc. are all clues. The following cryptogram pertaining to
procrastination is from the February 2002 edition of "Dell Easy Fast 'N'
Fun Variety Puzzles":
X'T
YTOHR WAFGCI RF ZAFL RF OQLOJY SGR FBB GARXQ RFTFHHFL LIOR X'T YGHW X LFGQV
TOZW O TWYY FB RFVOJ.
Mr. Steves, my fifth grade teacher, first introduced me to cryptograms. He used to give us 15 – 20
minutes to solve them and we usually worked in pairs. It is probably one of the reasons I got interested in
cryptography and ended up here. I
hope you enjoy them as the basis for your assignment. Thanks again Mr. Steves!