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:
  2. Use objects:

Grading rubric

Students write 8 classes. Each class is worth 10 points, for a total of 80 points. For each of those 8 classes:

So, a correct project that has no new JUnit tests, horrible style and no documentation would score:

80 - 16 - 16 - 32 - 32 = -16 points of 100 (yes, that is right — a negative score!)

The grader will not grade the documentation for the JUnit test classes (the existing tests are already documented). Students should use good style in writing tests in the JUnit test classes.

For any points deducted, the grader will put a CONSIDER tag saying how many points were deducted and why.

Here is a link to the General Instructions for Grading Programs.

Getting started

  1. In Eclipse, checkout the WordGames project.
  2. You will implement several classes, each of which includes a method with the following signature:

        public String transform(String stringToTransform);
    
  3. 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!)

    Reminder: Your code must include the required transform method, exactly as specified above.

    • So your Censor must have a transform method that takes exactly one argument (the String to transform).
    • If you are tempted to send two arguments to the transform method, or if you think that you need non-private fields, you are off the beaten path and should get help now.
    • It would be wise to get your instructor or an assistant to double-check this method before you continue.
  3. BONUS: 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".

    For NameDropper, we supplied ONLY tests for NameDroppers that drop the default name (Madonna). YOU must supply tests for NameDroppers that drop a non-default name.

    • We suggest that you add tests to this effect to EACH of the test methods already in NameDropper.
    • Thus, you will write several tests for the NameDropper class, not just one test (as in the other classes).
  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. BONUS: 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 positive whole number (I'll call it n). The SometimesShouter capitalizes every nth String that it is given (and leaves other Strings unchanged).

    Each SometimesShouter 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 SometimesShouter 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 SometimesShouter 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 SometimesShouter 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 SometimesShouter 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".

    Another example:

    • If a Repeater is given the String "Goodbye",
    • then the Repeater produces "GoodbyeGoodbyeGoodbyeGoodbyeGoodbyeGoodbyeGoodbye".
  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).