|
home—info—exams—lectures—labs—hws
Recipe—Laws—lies—syntax—java.lang docs—java.util docs
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:int ssf = 0; for ( int i=2; i < 10; i = i+3 ) { ssf = ssf + i; System.out.println( "i=" + i + "; ssf = " + ssf ); } |
int ssf = 0; |
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; } |
In general, what does the loop compute? (4-5 words of English.) What would be a more descriptive name for mysterySoFar?
Rewrite the fragment to use a for-each loop.
/** 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 ) { } |
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.
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.
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:
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() ); |
// 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.) |
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.
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
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.)
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. |
(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 ); |
Room( String _name, String _description, Treasure _t ) { this( _name, _description ); // One constructor calls another. this.treasures.add(_t); } |
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:
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.
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.)
Add some rooms and connections to the wiki, http://ru-itec120.pbwiki.com/grue-data-2007fall (password: “highlander”). Instructions are on that wiki page; be sure to follow the instructions exactly.
Specify connections only from your Rooms (to anywhere), and from the nexus to (at least one of) your Rooms.
Modify your program to use the provided GuiIO class, instead of TextIO 4.
This should require changing only two words of your program (change your declaration and initialization of your TextIO object to just use the type “GuiIO” instead). We carefully made sure that GuiIO has methods named display, promptForString, etc., so it can be easily swapped in -- “Plug'n'Play”. This explains why calling display was equivalent to calling System.out.println, but that layer of indirection has bought us flexibility.
This means that if you didn't follow the instructions on hw10, and you had your Explorer read/write the console/keyboard directly (without going through TextIO, then you have to go back and fix that in order to get your program to work.
Allow Explorers to carry any number of Treasures, instead of exactly two.
You'll find that this actually makes several
methods of your code shorter and simpler.
(There is no more need for Lint,
nor code which specific to the right pocket followed by
essentially-repeated code deadling with the left pocket.)
A hallmark of good design is that
not only does it make the program more flexible,
it simultaneously makes the code simpler.
Add chests, which require a key to be opened.
One simple way is to have “red chest” be openable if the if the Explorer happens to contain “red key” in their inventory.
Alternately, each chest might require some specific object to open (using ==). Note that this object might happen to be called “a chocolate egg”, and players might not know that it is also a key!
Make things appear differently, when certain tasks are completed.
For example, you might have it so that whenever an Explorer enters a certain room ("drawbridge control center"), it adds a new connection is created somewhere else in the world.
Alternately, each explorer might have a list of accomplishments; certain connections (or treasures) are displayed only to explorers who have certain accomplishments.
Allow multiple explorers (each with their own TextIO) who take turns exploring. (Each explorer might be off in their own different room entirely.) Let explorers who are in the same room interact.
(This would be a precursor to actually running your program in a distributed fashion -- with most of the program running on a server computer, but with TextIO or GuiIOs which are running each on a different client. Because we have divided the problem up effectively -- Rooms, Explorers, and IO are all different classes -- this might require some fancy networking to get started, but most of our code would be unchanged.)
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. ↩
home—info—exams—lectures—labs—hws
Recipe—Laws—lies—syntax—java.lang docs—java.util docs
©2007, Ian Barland, Radford University Last modified 2007.Dec.14 (Fri) |
Please mail any suggestions (incl. typos, broken links) to ibarlandradford.edu |