This project will help you show your mastery of vectors (esp. list management), classes, and libraries.
Write a program to allow the user to calculate the distance between cities on a map.
Sounds pretty complicated, eh? Don't worry, we'll make a few simplifications here:
The distances are calculated in map units on the 2D map.
Each city is given a set of coordinates relative to some point on the map. We'll call this origin: (0,0).
But in order to make the system useful, we'll have to add a few other features:
Each city has a name in addition to its coordinates. (You must be able to store cities with spaces in their names: Los Angeles, New York, etc.)
The user will select what action to take from a menu:
1) Enter city Information 2) calculate Distance between two cities 3) Print All cities 4) Quit
Make sure you allow them to choose their options by both the number and the capitalized letter(s) of the choice.
They cannot calculate a distance until at least two cities have been entered.
When they have more than two cities, show them the list of cities and have them pick the two cities between which to calculate the distance. Don't let them choose the same city for both ends of this mythical 'trip'.
When they have exactly two cities, assume these are the end-points and just print the distance between them.
Hint: You should have at least 2 classes — possibly 3 (see the options below). One will be Point — from the examples. (And, yes, you must use it as is!) Another should be a City class like:
class City { Point location; string name; public: double distance(const City & other) const { return location.distance(other.location); } Point get_location(void) const { return location; } // other methods and constructors here };
Don't forget to separate all the details of city handling from the details of list management.
Hint: Each class should be in its own library. Other libraries may also be used for collections of useful functions.
This assignment is (Level 5).
Add (Level 1.5) to allow the user to enter a city by either its name or by its position within the list. This option may be applied not only to the "distance" main menu choice — for entry of both cities but also again to either of the options below for a 'remove menu' item or for repositioning a city in the list. But each successive application is worth a little less, because it will be easier. Reduce it by (Level 0.5) each time — (Level 1) and then (Level 0.5) — for a total possible (Level 3)!
Add (Level 3) to add a third class to manage the list of cities. This will keep the main uncluttered by list management details. (This can be difficult, though. Keep straight in your head what is a city behavior and what is a list behavior! ...and consider yourself warned: some students have trouble remembering what is class behavior versus application behavior with just one class to design/use!)
To get you started:
class CityList { vector<City> list; public: bool full(void) const { return false; } bool empty(void) const { return list.empty(); } City get(vector<City>::size_type index) const; vector<City>::size_type get_num_cities(void) const { return list.size(); } bool set(vector<City>::size_type index, const City & new_city); bool add(const City & new_city); // other methods and constructors };
Add (Level 3) to add a menu option for sorting the cities in the list. You should further give the user the option of whether they want to sort the cities by name, x-coordinate, or y-coordinate. Perhaps a sub-menu like:
Sort by: 1) Name 2) X coordinate 3) Y coordinate 4) neVermind
Where the "nevermind" option simply returns to the main menu without actually sorting the city list.
You must write your own sort function(s) as per the discussions in chapter 6. You cannot use the sort standard library function!
Hint: Consider adding functions to test if one City object is less than another or greater than another — or both! Take as an extra argument to this function what class member variable the comparison should be based on — name, x, or y. Something like:
// compares two cities to see if caller is less than argument when // compared by name (0), x coord (1), or y coord (2) bool City::less(const City & other, short compare_by) const;
perhaps...
Add another (Level 1) to make the short argument an enumeration type instead. You can find out more about such types in the style guidelines elsewhere on the site.
Add (Level 1.5) to add a menu option to remove a city from the list. Present them with a numbered list from which to choose. The list they see should be numbered from 1 like a normal user would expect. (Of course, your list is numbered from 0 as is correct for programming.)
Add (Level 1.5) to add a menu option to reposition a city within the list. Present them with a numbered list from which to choose the city to move. Since they are trying to reposition that city, go ahead and remove it from the list — but don't forget to keep a copy! Then present the list again with an extra dummy position numbered .size()+1 and let them choose which position to move the selected city IN FRONT OF. The lists they see should be numbered from 1 like a normal user would expect. (Of course, your list — the one stored in the vector — is numbered from 0 as is correct for programming.) When they enter the new position as .size()+1, — well, not literally — remember this means they want to move the city to the end of the current list.
There are several ways to accomplish this — the above outlined approach is just one possibility. Be creative.
(For instance, my personal suggestion is to let them really enter the phrase city_1 before city_2; where city_1 would be the position of the city to move and city_2 would be the position of the city in front of which to place the first city...but maybe that's just me. After all, they might sometimes enter after instead of before. Heck, they'd need to if the new position would be after the currently last city in the list. But, then again, it might be worth an extra (Level 2) to you...*shrug*)
If you did all above options, this project could be worth as much as (Level 19).