ulrail.gif

HW J5: Writing Classes

  ur-2c.gif urrail.gif
blrail-nonavbar.gif

Home | Resources | Homeworks | Exams
Slides | Labs | Contacts | Submit | TAs

br-2a.gif   br-2c.gif brrail.gif
spacer.gif spacer.gif spacer.gif

Purpose

This assignment will give you practice implementing your own classes, and calling methods within them.  To give you a sense for the process of writing larger programs, the remaining assignments in CS 101 will build toward a simple text game.

Background -- Space Trader

Among the earliest computer games, developed in the 1970s, were text-based adventure games. One of the best early games was called Space Trader, in which a player travels to distant stars buying and selling cargo, in an attempt to make money. For example, a player could arrive at a star system and see that gold was selling very cheaply, buy it, and then travel to another star and sell it for a large profit. A single person could play against the computer, and multiple players could play against each other (with or without the computer also pretending to be a player in the game). Even though it lacked graphics (because the sophisticated hardware had not yet been invented), Space Trader and games like it such as Adventure significantly increased the popularity of computers because, simply, they made the computer fun!

In the next few assignments you will build the components for a rather simple text-based Trader game. We designed these assignments so that ultimately you will have the option of specifying what you are buying and selling, and where (this will be done in the Descriptions class).  The game has also been simplified in that you are not competing against anyone. Rather, you're just traveling from point to point, opportunistically buying and selling products in an attempt to make money.

Over the next HWs and Labs,  you will ultimately design and implement 10 Java classes:

  • [HWJ5,  due Fri Mar 31] Location: The Location is a place where buying and selling of goods can occur.

  • [Lab 9,  week of April 3] Parser: used to read in user input from the keyboard for use in a computer game.  A parser is the part of a computer program that takes in user input and translates it into another form. 

  • [HWJ6,  due Fri April 7] Vehicle: The Vehicle is used to move between locations (and thus markets). The vehicle starts with an initial amount of fuel, which is consumed as you travel between Locations. Because you can't really do much without your vehicle, the vehicle is really the embodiment of you. Your money is kept in your vehicle.

  • [HWJ7,  due Fri April 14] Inventory, Cargo, and Market: The inventory is used to represent the goods being bought and sold in the market, as well as being used to represent what items you're carrying around in the vehicle. The market -- in addition to carrying an inventory -- represents the actions that can occur at a Location (e.g., buying an item, selling an item, etc.).  Cargo is both sold at markets and carried in your vehicle.

  • [Lab 10, week of April 10] Descriptions: The class will allow us to generate a random name for a location ("Ariel", "Whitefall", etc.) and a random name for a cargo type ("Gold", "Platinum", etc.), and a random cargo cost factor (5.0, 4.0, 10.0, etc.). The "cost factor" represents the mark-up (or opposite, as the case may be) of items in that Market. For example, a loaf of bread is MUCH more expensive in NYC than it is in Charlottesville.

  • [Lab 11, week of April 17] Map: used to print the location of the Locations

  • [HWJ8, due Tue April 25] Universe and Game: The Universe represents a particular X-Y section of the space (2-d, not 3-d). It contains a number of Locations. The Game is the top-level class that runs "main". This Game class also sets a number of the global parameters (such as the maximum cargo price).

Note that after each Java Homework (HW J5 on Fri Mar 31, HW J6 on Fri Apr 7, HW J7 on Fri Apr 14,and HW J8 on Tues Apr 25), you will have a "working system".  That is, your code will be a fully working early version of the game.  It may not do much, though.  Sometimes we will provide you with the working "class" file (bytecode) of a Java class that you'll make in the future, and at other times we might provide the skeleton source code of a particular Java class. More specifically:

  • [After HWJ5] The only classes are Location and the first version of Game (Game.java and a shell of Market.java are provided to you). This first version of Game.java will create a bunch of locations and simulate traveling between them.   There is no player interaction at this point.

  • [After HWJ6] The only classes are Vehicle, Location, Parser, and a new version of Game (which is provided to you). This second version of Game will create a bunch of locations, and you (the player) can travel between them. 

  • [After HWJ7] The new classes added are Inventory, Market, Cargo, and Descriptions, as well as a new version of Game. This is similar to the previous working version, but you can now buy and sell things.

  • [After HWJ8] The new classes are Map and Universe, as well as the last version of Game, which is all of the classes. This is the final version of the HW.

Specifically, in this homework (HWJ5) you will develop the Location class. To get started, create a new directory called HWJ5, and download Market.java, Location.java, and Game.java (Right click on each link, select "save as", and save them all to this directory). Note that in this assignment the only file you should modify is Location.java.  The Market class that we provide is intentionally empty -- it's just included so that your code will compile.  You will be writing the Market class in HW J7.

Design of the Location Class

Note that you MUST name your methods exactly as specified (including the proper capitalization) -- otherwise, our test programs will not realize you have the methods written, and you will get zero credit for them.

Attributes

The Location class should use instance variables to represent the following attributes.  They should all be private.

  • posX (double): x pos of location in X-Y coordinate space
  • posY (double): y pos of location in X-Y coordinate space
  • name (String): the name of the Location (e.g., "Pluto")
  • appearance (String): what the location looks like to the human eye (e.g., "sunny")
  • market (Market): this is where the buying and selling of goods occurs -- which goods are available, at what price, etc. The market of each Location is unique. (We will provide you the implementation of the Market class for this assignment -- later, you will write it yourself).

Constructors

This class will have three constructors.

  • Location (): the default constructor, it initializes all the values to some default value.  The position should be (0,0).  The name and appearance should be set to something (you pick), and the market to null.
  • Location (String theName, String theAppearance, double thePosX, double thePosY): the constructor that sets initial values for name, appearance, and X-Y coordinates; market should be set to null.
  • Location (String theName, String theAppearance, double thePosX, double thePosY, Market theMarket): the constructor that sets initial values for name, appearance, X-Y coordinates, and market.

Accessors/Mutators

As the instance variables in this class are private, they will need to be manipulated via accessor and mutator methods as we have discussed during lecture.  Thus, you must include an accessor and mutator method for each of the above fields in your class.  The name of the accessor/mutator methods should follow the standard Java naming conventions (i.e. getPosX(), setName(), etc.).  

Other methods

The location class should also support the following methods:

  • double getDistance (Location other): calculates and returns the distance from this Location to the "other" Location.  This uses the distance formula () to compute and return the distance between locations.
  • String toString (): returns a string representation of the Location (e.g., "Houston (55.0, 12.5)"). Note: the appearance field should not be included here, as it will used separately (e.g., it doesn't ALWAYS make sense to refer to Houston as "hot Houston", does it?)

All-at-once or Incremental?

In this and the remaining assignments, you are being asked to write a small number of Java classes that will fit like a puzzle piece into a version of the complete game. So, there are basically two ways to go at this. The first way is to just attempt to write the Java class(es) from start to finish, and then compile and run the "Game" file that you are provided. The difficulty with this approach is that something will inevitably go wrong upon executing the Game, and it might not be obvious what happened -- after all, you just defined a bunch of new methods and it's not obvious which ones have been invoked apparently successfully, and which one has caused the program to bomb (directly or indirectly). So you can try this approach, but it might be frustrating and time-consuming to debug.

A different approach is to first implement all of the methods (of course with the proper method signatures) in the following way. First, write a statement that returns a valid value as necessary to make the compiler happy. Don't worry about the proper value right now. (Note that this line is not required if the method returns "void"). Then, make the body of each method such that it prints to the screen that this method has been entered and then immediately aborts the program. An example of this is:

             public double getDistance (Location other) {
                    System.out.println("error -- getDistance");
                    System.exit(0);
                    return 0.0;
             }

This way, you can write the methods as they are encountered in the actual program execution (meaning, when the Game class calls the methods). When your program executes and executes a new method, go in and replace this "error body" with your real code, and re-run it. If your next error that you encounter is another one of your "error bodies", and you have reasonable confidence that the code you typed in for the first one is correct, then move on to this new method body and and fix that.  Note that merely getting your replacement code for this "error body" code to execute without an obvious error is NOT equivalent to the code being correct (as it could just do the wrong thing), but this process DOES allow you to incrementally write code and test it. Once you're happy with the program execution, then you need to make sure that you have written a real body for each other methods -- sometimes you will be asked to write methods that are not not actually invoked until a later assignment (but they're still important to write now).

Of course you can write separate test code that exercises the functionality of your Location class, but this "in-situ" testing is extremely important.

In this assignment in particular, the all-at-once approach might be more attractive, particularly since the amount of code you need to write overall is not very much. However, it makes it difficult to debug your program if you do it that way.

It should be noted that some people really like the all-at-one-time nature of the first approach, while a lot of people like the incremental nature of the second approach. Choose the one (or some other different approach) that you feel most comfortable with!

Game Simulation

We have provided Game.java, which includes the main() method.  This program creates five "Star" locations. Next, the program starts at the first location and travels once to each of the other locations in a random order. As you see in Game.java, we generate random numbers by first  creating a Random object.  Random is a class within the java.util.* library.  A Random object is created via the default constructor: Random rand = new Random();  To generate a random integer, you then call nextInt().  For example, to generate a random number from 0 to 9, you would call: int x = rand.nextInt(10);  Note that the integer generated is between 0 and n-1, where n is the parameter (in this case, 10).

As you also see in Game.java, we simulate travel in such a way that it is instantaneous to travel from one place to another.  While not the most realistic, it allows for the program itself to be simple (as one does not have to "wait" for a period of time to simulate the time taken to travel).

Though the outcome of the trip is different each time because of the use of the Random class, the output should look something like this:

Welcome to CS101 Space Trader v1!

You travel at 10.0 million kilometers per second.

You are starting at sunny Geminorum (91.0, 69.0)

You will next travel to colorful Cygni (40.0, 8.0).
This is a distance of 79.51100552753688 million kilometers.
Traveling: ........ Arrived safely!

You will next travel to tired Orionis (74.0, 49.0).
This is a distance of 53.2634959423431 million kilometers.
Traveling: ...... Arrived safely!

You will next travel to exciting Andromedae (6.0, 22.0).
This is a distance of 73.16419889536138 million kilometers.
Traveling: ........ Arrived safely!

You will next travel to barren Ursae Majoris (85.0, 81.0).
This is a distance of 98.60020283954795 million kilometers.
Traveling: .......... Arrived safely!

Congratulations, Space Trader!
You have successfully visited all 5 locations in our game!
You traveled 304.5389032047893 million kilometers.
Take the rest of the day off, Space Trader -- you deserve it!

Note that although we provide the Game.java code, it is important that you understand how it works (hint!).

Test Code

This first version of Game.java file includes most of what you will need to test your classes.  It is important to confirm that the output is what you expect it to be.  The easiest way to do this is to copy-and-paste the output from an execution run into comments in your file -- this will be explained in lecture the week of Monday, 27 March.

Submission

The good programming practices from HW J1 need to be in this homework as well.

When you are finished, submit the Location.java file.

spacer.gif
spacer.gif footer-middle.gif spacer.gif