RU beehive logo ITEC dept promo banner
ITEC 120
2007fall
ibarland,
jdymacek

homeinfoexamslectureslabshws
RecipeLawsliessyntaxjava.lang docsjava.util docs

hw13
gRUe pt. IV

All parts due 2007.Nov.30 (Fri) 17:00. You only need turn in files which have changed since your hw13.

Part (a), Short answer:
  1. Declare and initialize a plausible “so-far” (accumulator) variable for a loop which...
    1. counts the number of space characters in a String
    2. determines whether or not a String contains any newline characters.
    3. finds the heaviest Treasure in a non-empty list of Treasures ts.
  2. What lines does the following print out?
    (Hint: walk through the code by hand, keeping track of what each variable is.)
    int ssf = 0;
    for ( int i=2;  i < 10; i = i+3 ) {
      ssf = ssf + i;
      System.out.println( "i=" + i + "; ssf = " + ssf );
      }
    
  3. The following loop is probably not at all what the author intended, for several reasons. What lines does the following print out?
        int ssf = 0;
        int i = 0;
        for ( int i = 2;  i < 10;  i = i+3 ) {
          int ssf = 0;
          ssf = ssf + i;
          System.out.println( "i=" + i + "; ssf=" + ssf );
          i = i + 3;
          }
      
  4. For this and the following problems, assume that deadlines is of type java.util.LinkedList<Date>, and refers to a non-empty list.

          Date mysterySoFar = deadlines.get(0);
          int i = 0;
          while (i < deadlines.size() ) {
            Date d = deadlines.get(i);
            if (d.comesBefore(mysterySoFar)) {
              mysterySoFar = d;
              }
            i = i+1;
            }
        

    1. Suppose that deadlines contained four Dates in the following order: new Date( 2007, 1, 1), new Date( 2008, 1, 15), new Date( 1988, 9, 10), new Date( 2008, 1, 15). After the loop runs, what will mysterySoFar be equals to?
    2. In general, what does the loop compute? (4-5 words of English.) What would be a more descriptive name for mysterySoFar?

    3. Rewrite the fragment to use a for-each loop.

    4. Rewrite the fragment to use a for loop.
  5. Write a loop which computes 1³+2³+3³+...+1000³.
    You can use any sort of loop, although a for loop is particularly natural when counting 1...1000. (This is simpler than computing the number of oranges in any sort of pyramid.)
  6. Use a for loop to write the following function.
      /** Return a String concatenated to itself mutliple times.
       * @param n the number of copies to make.
       * @param word the String to copy.
       * @param a String containing `n` copies of `word`.
       * Examples:
       *     Linguistics.stringTimes( 3, "ho" ) = "hohoho"
       *     Linguistics.stringTimes( 1, "unary" ) = "unary"
       *     Linguistics.stringTimes( 0, "turkey" ) =                 
       *     Linguistics.stringTimes( 4, "" ) =                 
       */
      public static String stringTimes( int n, String word ) {
        
    
    
        
    
    
            
        }
        
    You can use any sort of loop, although a for loop is particularly natural when counting 1...n.
    Hint, for figuring out your accumulator variable: If somebody calls stringTimes( 1000, "hi" ), what partial result will you have built up after going through the loop 500 times? (It should be the same type as the final answer you're trying to compute!) How will you update that value the 501st time through?

parts (b),(c)

The last essential step to our Grand Repository of Underground Entertainment (gRUe) will be to add connections between rooms. Every room will be connected to zero or more other Rooms; connections can be one-way. (That is, you might be able to get from room A to room B, but not back.)

Before proceeding, you'll need to have at least 3-4 Rooms already created in your unit-tests for Room. Note that each method below requires 2-5 lines of code, no more.

  1. Write a method explore, which calls exploreOnce repeatedly, until a command like “quit” is entered.

    Note: Clearly, exploreOnce will know when the user has indicated they want to stop. But how will explore know that? Easy -- modify exploreOnce so that it returns this bit of information, and explore uses that returned value. (Do not create an entire field, just to have one method communicate with another; fields are meant to hold state about an Explorer, whereas parameters and return values are the way methods pass information back and forth.)

    Hint : Ask yourself the usual questions:

    No test cases or drawings are needed for this method, as it is solely interactive.

  2. Update Rooms so that they have one more field, which holds all the adjacent Rooms (zero or more).

    Newly-created Rooms will have no other adjacent Rooms.

    Complete the provided picture, showing what things look like if there are four Rooms A,B,C,D such that:

    (Note how we don't know what fields are inside a LinkedList, so our drawing acknowledges this vagueness. Also, this drawing actually shows that Strings are objects, something we usually gloss over in drawings.)

    Your test case will make a brand new Room, and be sure that it has initially no neighbors. There are different ways of doing this; two that spring to mind are:

            // If you write your own static test-driver method, you might include:
    
            Room roomA = new Room( /* ... details omitted */ )
            System.out.println( "roomA should have 0 neighbors: " + roomA.getAdjacents().size() );
          
    or
            // If you use a unit-test case, you can manually add a test case:
            assertEquals( 0, roomA.getAdjacents().size() );
            // (Presuming roomA was one of the rooms declared in the test-fixture.)
          
    Of course, the exact names of your fields and/or getters might be different.

    Caution:

    Important: your Room's toString method, when processing the list of adjacent rooms, should not call toString of any of its adjacent rooms. (This includes not call the list's default toString, since the LinkeList's toString is programmed to call the toString of everything inside the list.)

    Why not? Because if roomB has roomC as a neighbor and in turn roomC has roomB as a neighbor, then printing would be infinite: roomB.toString() would attempt to make a string using (in part) roomC.toString(), but roomC.toString() would attempt to make a string using (in part) roomB.toString(), but roomB.toString() would attempt… you get the picture. Java will report “Stack overflow”.

    Instead: A Rooms toString might well mention the names of all its neighboring rooms, just not its neighbor's neighbors.

  3. Add a Room method connectTo (use that exact name!), which takes one input (the adjacent Room to connect to), and adds that Room to the list of adjacent Rooms.

    What changes in your drawing above correspond to roomD.connectTo(roomC)? (Either make a whole new “after” drawing, or add to it using a different color of ink.)
    Hint: the number of changes in your drawing will correspond to the number of lines of code this method will require.

    A plausible test case would assert that (after calling roomD.connectTo(roomC)) it's the case that roomD.getAdjacents().contains(roomC) is true, but roomC.getAdjacents().contains(roomD) and roomC.getAdjacents().contains(roomB) are false. Note that we're using the List method “contains”.

    After the above code, it is possible to get from roomA to roomB (but not back to roomA). Write some more test cases for the method, then write the method, and then test your code before proceeding. (You should include more than just this one test. What happens if you have a room connected to itself? Can you have one room which connects to several others?)
  4. Add a method biconnectTo (use that exact name, please), which makes a two-way connection between Rooms.

    Draw a picture of what things look like after calling roomD.biconnectTo(roomB). 2 Write reasonable test-method.

    Don't repeat code (duh).
    Hint: Remember, this is an ordinary local-variable which you can use just like any other local-variable/parameter. (The only thing special about this is how java automatically declares and initializes it for you in every (non-static) method.)

    After this code, it is possible to move from roomD to roomB and back.
  5. Add a Explorer method moveTo. The method takes an int, looks up which adjacent-room indexed by that int, and changes the Explorer's current-room room to be the new room. (Think to yourself: Should this method be static?)

          // Suppose that e1 is an Explorer whose current Room is roomA,
          // and that roomA has two neighboring rooms (roomB and roomC,
          //    with indices 0 and 1 respectively).
          e1.moveTo(1);
          // Now, e1's current room should be roomC.
        
    This method will be similar, in some ways, to grab. It should return a String, with a message somehow indicating that the room has changed.

    (I'm going to stop saying that you should write your test cases before you write the code, and that after you write the code you will run your test cases before proceeding; you know all that by now.)

    Of course, we can use local variables to name sub-results of this one line, if it helps:
        Room curr = this.getCurrentRoom();
        java.util.LinkedList<Room> nhbrs = curr.getNeighbors();
        Room dest = nhbrs.get(i);
        this.setCurrentRoom( dest );
     
  6. Update your exploreOnce method to allow somebody playing your game to move the explorer to different Rooms. (Hint: in hw12, you've already written and tested a version of select which takes a list of Rooms.
  7. You already have created some other rooms as test cases, on the bench. But we'll want to have some Rooms which exist when we're running our program (playing the game), and not just testing. To this end, write a method called something like setupRoomConnections, which creates several additional Rooms, and makes connects between them. (Think to yourself: Should this method be static?) Then, when somebody makes an explorer, be sure to3 setupRoomConnections, so that the new Explorer has somewhere to go!
  8. In preparation for the next step, we'll make two small changes to our Room.java. You don't need to make test cases for these.
    1. Make a Room constructor which takes only two arguments (a name and description -- but no Treasure). It creates a new Room holding no Treasures, naturally enough.
    2. Optional: modify your three-argument Room constructor to call your two-argument constructor, yielding something along the lines of
                Room( String _name, String _description, Treasure _t ) {
                  this( _name, _description );  // One constructor calls another.
                  this.treasures.add(_t);
                  }
              
      This way we retain a single point of control for initializing a Room's name and description. Note how “this(…)” is a new form of syntax, different from other method calls or constructor calls.
    3. Write a Room method addItem(Treasure), which inserts another Treasure into the Room.
      Update your drop method(s) to use this method.
    Why did we make these changes? So that when creating Rooms from the wiki, it's possible to create rooms without Treasures, and also to add a whole bunch of Treasures to a Room (without needing some Explorer to drop anything).
  9. Finally, write a method which lets you explore using the rooms from the Wiki. Use the provided class Entry (slightly modified Nov.28 17:15, to give a better error message when a wiki entry has a Treasure with a non-numeric weight).

    See the comments at the start of Entry.java, but the gist is simple: You'll call a Entry.buildWorld, which returns a Room (which presumably has connections to other Room/s). Entry.buildWorld actually calls methods you've written:

    If your signature for any of these methods differs from what Entry.java expects, you'll have to fix one or the other so they match.

    It's worth realizing that by providing just these five methods, your code is interoperable with code written by somebody else entirely, regardless of what fields you have and how you implement your methods.

    You might find that there are errors on the wiki page, where people's items don't exactly follow the wiki instructions, and therefore the provided code can't parse the wiki. Fix the wiki page as needed.

    You shouldn't need to make any changes to Entry.java, but you are welcome to. Note that you have learned enough to understand everything that file does, with the exception of using a particular class (java.util.Map), which you'll learn about if you take ITEC220. In fact, everything you need to know about about Map is explained in comments inside the method Entry.buildWorld.

extra credit: standalone program

hw-ec05 is due 2007.Dec.07 (Fri) 17:00, the last day of classes.
Note: Some of the following may actually become part of hw14, rather than extra credit. (Particularly, the first three or four items.)


1Yes, each time we call exploreOnce might be lots of state-change happening to the Explorer's fields, but that's not what the loop itself is caring about.      

2You can make this a static method, if you prefer. The rationale against a regular method is that the two rooms are equally important, so it seems odd to have roomA be considered the “primary” instance, and roomC is a the subsidary input to the action being performed on roomA. For comparison, in the one-way connectTo method, the asymmetry between the two Rooms is perfectly natural. You'll have to modify the one line of Entry.java which calls this method; no problem.      

3 If you later have multiple explorers occurring, then you'd want to take precautions not to call this room-setup method twice, but that's not an issue for this assignment. If you want to make sure this method isn't performed twice, you can make a static boolean haveAlreadyInitializedRoomConnections, and use that to make sure that the method doesn't re-initialize things. (A more appropriate solution is to read about static initialization blocks.)      

4 Why are we getting rid of TextIO? Oddly, if a program is started by double-clicking, there is no console-window for it to write to. Thus System.out.println (and therefore TextIO) is useless for standalone programs.      

5Conceivably, those Strings could be run-time options given to your program, but if you start your program by double-clicking there is no mechanism to specify what Strings to pass in.      

homeinfoexamslectureslabshws
RecipeLawsliessyntaxjava.lang docsjava.util docs


©2007, Ian Barland, Radford University
Last modified 2007.Dec.14 (Fri)
Please mail any suggestions
(incl. typos, broken links)
to iba�rlandrad�ford.edu
Powered by PLT Scheme