CSSE 220: Object-Oriented Software Development
WordGames

Work on this exercise by yourself, but be quick to ask questions of your instructor, student assistants and classmates as desired.

Goals

Solidify your understanding of how to:

  1. Implement a class:

    • The process for doing so:
      • Writing documented stubs before coding
      • Writing unit tests before coding
    • Implementing an interface
    • Writing constructors
    • Writing methods
    • Using fields
  2. Use objects:

    • Constructing objects with the new operator
    • Invoking methods on objects with the dot notation
    • Reading and applying the API (Application Programming Interface) for a class

Grading rubric

Each class that you write counts 10 points:

  • 3 points for writing a good collection of boundary tests
  • 7 points for writing a good collection of tests for other things that might break

Additionally, your score is reduced by 1/2 if your class:

  • Is incorrect.
  • Lacks correct documentation.
  • Disobeys our code conventions.

Additionally, your score on the tests for a class is the minimum of the score on your tests and your score on tests that you peer-reviewed.

  • So if you screw up your peer review, you are screwed too.

Finally, recall that this is a learning exercise, not a test. Hence, we will grade the “first draft” of your tests/code and then you may submit a second draft with errors corrected.

  • But don't abuse this privilege; strive to get it right in the first draft.

Getting started

  1. Use the class notes associated with this exercise as needed.
  2. In Eclipse, create a new Java project called WordGames

  3. Add your project to your individual repository for this course.
  4. You will implement several classes, each of which implements the StringTransformable interface:
    /**
     * A StringTransformable object can transform one String into another String.
     *
     * @author David Mutchler, based on an idea from Lynn Stein
     *         in her Rethinking CS 101 project.
     *         Created Mar 12, 2009.
     */
    public interface StringTransformable {
    	/**
    	 * Transform the given String into another String.
    	 *
    	 * @param stringToTransform The String to transform
    	 * @return The transformed String
    	 */
    	public String transform(String stringToTransform);
    }
    

    Add the above StringTransformable interface to your project now.

  5. Implement each of the classes described below, one by one. For each class that you implement, use this process drawn from Extreme Programming Rules and Practices:

Classes to implement

  1. [Your instructor will do this one with you.] Use the above process to implement:
    Shouter: given blah, produces the result of changing all the characters in blah to upper-case.

    • For example, a Shouter would:

      • transform "Alice in Wonderland" to "ALICE IN WONDERLAND"
      • transform "Tweedledee and Tweedledum" to "TWEEDLEDEE AND TWEEDLEDUM"
  2. [Your instructor will do part of this one with you.] Use the above process to implement:
    Censor: given blah, produces the result of replacing each occurrence of the character (not string) foo in blah with an asterisk, where foo is the character that the particular Censor censors.

    • Thus each Censor has its own character (and just one such character) that it is told about when it is constructed and that it censors. If it is not told about any such character, it will censor the letter 'e' by default.
    • For example, one Censor might censor the letter 'e'. Such a Censor would:

      • transform "Alice in Wonderland" to "Alic* in Wond*rland"
      • transform "Tweedledee and Tweedledum" to "Tw**dl*d** and Tw**dl*dum"
    • But another Censor might censor the letter 'W'. Such a Censor would:

      • transform "Alice in Wonderland" to "Alice in *onderland"
      • transform "Tweedledee and Tweedledum"to "Tweedledee and Tweedledum" (i.e., leave it unchanged — case matters!)
  3. Use the above process to implement:
    Pedant: puts "Obviously " before its given string.

    • For example, a Pedant would transform "Roses are red" to "Obviously Roses are red".
  4. Use the above process to implement:
    NameDropper: puts "foo says " before its given string, where foo is the name that the particular NameDropper drops.

    • Thus each NameDropper has its own name (a String) that it is told about when it is constructed and that it drops whenever it transforms a String. If it is not told about any such name to drop, it will drop the name "Madonna" by default.
    • For example, one NameDropper might be given the name "Confucius". Such a NameDropper would:

      • transform "An apple a day, Keeps the doctor away!" to "Confucius says An apple a day, Keeps the doctor away!"
      • transform "this is silly" to "Confucius says this is silly"
    • But another NameDropper might be given the name "Charlie Chaplin". Such a NameDropper would:

      • transform "very little" to "Charlie Chaplin says very little"
      • transform "Tweedledee and Tweedledum"to "Charlie Chaplin says Tweedledee and Tweedledum".
  5. Use the above process to implement:
    Counter: puts a number in front of each input, that goes 1, 2, 3, ...

    For Example:

    • If a Counter first transforms "Hello", the Counter would produce "1. Hello".
    • If the same Counter next transforms "Goodbye", the Counter would next produce "2. Goodbye".
    • And so forth.
    • Note that each Counter takes what it is given and begins by putting "1. " in front of it.
      • So if you construct one Counter, make it transform some Strings, and then construct another Counter, and then continue making the Counters transform Strings, the Counters are “out of sync” — see test case below.

    A good way to functionally test this class is to:

    1. Construct a single Counter.
    2. Call the Counter's transform method several times.
      • Your Counter should count: 1, 2, 3, ...
    3. Now construct a second Counter, and call both of the Counters' transform methods several times.
      • Your first Counter should continue counting from where it left off: 4, 5, 6, ...
      • Your second Counter should start counting: 1, 2, 3, ...

  6. Use the above process to implement:
    Doubler: repeats the given string two times, with a single space in between.
    • For example, a Doubler would transform "Violets are blue" to "Violets are blue Violets are blue".
  7. Use the above process to implement:
    SlowThinker: produces whatever it was given the previous time.

    For example:

    • If a SlowThinker is asked to transform "Hello", then "Goodbye", then "See you later",
    • that SlowThinker first produces "" (the empty string), then "Hello", then "Goodbye" (and so forth, always one behind its current input).

    As with Counter (and indeed, as with all these StringTransformers), each instance of SlowThinker is independent of other instances of SlowThinker.

    This one is challenging! Don't spend more than 30 minutes on its code (unless you want to!).

  8. Use the above process to implement:
    SometimesShouter: has a nonnegative whole number (I'll call it n). The SometimesCapitalizer capitalizes every nth String that it is given (and leaves other Strings unchanged).

    Each SometimesCapitalizer has its own number (so n should be a field that can be set using a constructor. If it is not told about any such number, it will use 2 (capitalizing every other string it is given) by default.

    For example:

    • One SometimeCapitalizer might have 3   as its value for n. Given the following Strings (in the order listed):

      • How are you today?
      • Not bad. How 'bout you?
      • Not too good, I'm afraid.
      • Why is that?
      • Well, I'm terribly sorry, but I've just run over your cat.
      • Oh no!
      • Well, to make up for it, I'd like to replace your cat.
      • OK, but how are you at chasing mice?
      • -- From the movie Mary Poppins (and many places before that)

      this SometimeCapitalizer would produce (in order):

      • How are you today?
      • Not bad. How 'bout you?
      • NOT TOO GOOD, I'M AFRAID.
      • Why is that?
      • Well, I'm terribly sorry, but I've just run over your cat.
      • OH NO!
      • Well, to make up for it, I'd like to replace your cat.
      • OK, but how are you at chasing mice?
      • -- FROM THE MOVIE MARY POPPINS (AND MANY PLACES BEFORE THAT)

    • Another SometimeCapitalizer might have 4   as its value for n. Given the same Strings as above, it would produce (in order):

      • How are you today?
      • Not bad. How 'bout you?
      • Not too good, I'm afraid.
      • WHY IS THAT?
      • Well, I'm terribly sorry, but I've just run over your cat.
      • Oh no!
      • Well, to make up for it, I'd like to replace your cat.
      • OK, BUT HOW ARE YOU AT CHASING MICE?
      • -- From the movie Mary Poppins (and many places before that)

    Just ask if you have questions about what a SometimesCapitalizer is supposed to do.

  9. Use the above process to implement:
    Repeater: transforms the given String into N   copies of the given String, where N   is the length of the given String.

    For example:

    • If a Repeater is given the String "Hello",
    • then the Repeater produces "HelloHelloHelloHelloHello".

  10. Use the above process to implement:
    Evener: transforms the given String into a String consisting of only the characters whose positions in the given string are even.

    For example:

    • If a Evener is given the String "abcdefghij",
    • then the Evener produces "acegi".

    Note that in the above definition, the first character's position is “even”, because we start numbering from 0 (as in the C language) and we consider 0 to be an “even” number.

  11. (Bonus problem, do it only if you are having fun with it!) Use the above process to implement:
    UbbiDubbier: transforms the given String into Ubbi Dubbi.

    • The Zoom site explains the rules for their Ubbi Dubbi language:
      "All you have to do is say UB before every vowel sound."
    • Don't worry if your UbbiDubbier doesn't know how to recognize every vowel sound — that's actually an open research problem!
    • If you wish, you can compare your UbbiDubbier to the Ubbi Dubbi translator at Zoom's site. (Note that theirs is not perfect either—try words with adjacent vowels that belong to different syllables, e.g., idea or Leah).