Adventure


General

  • All submissions must include a work history to be worth credit.
  • Submit all files to Canvas. Make sure to name file(s) EXACTLY as specified - including capitalization.
  • Make sure your program accepts input in EXACTLY the order and format given. Do not ask for extra input or change the order of inputs.
    If you want to make an expanded version of a program that and get feedback on it, email it to me or show me in class.
  • Slight variations in output wording/formatting are usually fine (as long as formatting isn't part of the assignment).
    If you do not get the right final output, print out some evidence of the work your program did to demonstrate your progress.
  • Readability and maintainability of your code counts. Poor formatting, confusing variable names, unnecessarily complex code, etc… will all result in deductions to your score.

Objective

Learn how to use pointers to link objects.

Background

We will be creating a representation of a map like this one:

A map of the caves

We need to be able to have locations that connect to each other; it should be possible to travel from "the musty passage" to "a twisting shaft". But we also want to make sure there is only one copy of each location - we can't have two different copies of "a twisting shaft", one that you get to from "the musty passage" and another that you get to from "the shores of an underground lake".

Once this is built, we will use it as the basis for a simple text game where the player tries to find their way to the exit.

Setup

You should use the Combo Project Template in either a codespace or a local development environment to do this assignment.

While working on this assignment, MAKE sure that you are generating a worklog with time stamped entries.

You are provided with this file of unit tests to ensure that your Location class works correctly. Copy that code into tests.cpp.

You are provided with some starter code to use in main.cpp. You won't need it until the last part of the assignment.

Then add new files Location.h/Location.cpp to your project. They will have the declaration and definition for your Location class, respectively.

Edit your Makefile to make use of the new files. It should end up looking like:

...existing content...
HEADERS = Location.h
...existing content...
SHARED_FILES = Location.cpp
...existing content...

Location Class (80%)

Note: You should not work in main.cpp until this part is complete and all tests are passing.

The Location class represents a location in the game. Each location can be connected to up to 4 other locations (the locations that are North, South, East and West of the current location). As the player explores locations, they drop bread crumbs to mark where they have been before, so each room keeps track of whether it has been visited yet.

classDiagram direction LR class Location { ...member variables... +Location() +Location(name : string, isExit : bool) +getName() string +getDescription() string +hasNeighbor(dir : Direction) bool +getNeighbor(dir : Direction) Location#42; +setNeighbor(dir : Direction, other : Location*) isExit() bool +visit() +isVisited() bool } Location --o Location

The member variables are intentionally unspecified. Decide what data you need to track and how to do it.

Pointer symbols generally would not be represented in UML. We are showing them to make clear that we are using Aggregation, not Composition. As usual, other C++ syntax details, like const and reference types do not appear in the UML - use them where appropriate.

The functions you need to implement are described below. Use the provided tests to verify your implementation. Try to implement as little as possible to get each test to compile and run, and then add more code to get the next test working. Leave all tests that compile and run in place - they are proof that your class works correctly. If there is a test that will not compile, or causes a runtime error, comment it out so the rest of the tests can run.

You do NOT need doxygen comments for the functions. You can add them if you want, but they are not required for this assignment.

Direction should be defined as an enumeration inside your .h file before the class, like this:

enum class Direction { NORTH, SOUTH, EAST, WEST };

(The tests will use this enum, so make sure you have it defined exactly like this.)

Function Descriptions

Location ()

This should set the name to "?", have an empty list of neighbors, and set exit and visited to false.

Location (string, bool)

The two arg constructor should set the name and exit members, setting the rest to null or false as appropriate.

hasNeighbor

Returns true if there is another location in the specified direction, false if there is not (nullptr).

getNeighbor

Returns a pointer to the neighbor in the indicated direction (or nullptr if there is not a neighbor).

setNeighbor

Stores the indicated Location pointer as the designated neighbor.

visit

Marks a room as having been visited.

isVisited

Returns true if a room has been visited.

isExit

Returns true if this Location is an exit.

getName

Returns the name of the location.

getDescription

Should return a string containing the name of the location, a list of the directions you can leave in and if it has been visited before. The first time we get the description for a room, it might say:

"a deep dark cave. Exits: north east south."

Or, for a different room that had been visited, something like:

"a musty passage. You have been here before. Exits: north east south."

Main (20%)

Your main.cpp file should have the code for the game. It will build a map like the picture below and then run the game of trying to find the exit.

A map of the caves

The map you create should exactly match this one.

Make sure you do not unintentionally copy your Location objects while setting up your pointers.

Good:

locations.at(0).setNeighbor(Direction::NORTH, &locations.at(1));

Bad:

Location loc1 = locations.at(0);
Location loc2 = locations.at(1);
loc1.setNeighbor(Direction::NORTH, &loc2);
// loc1 and loc2 are COPIES of the locations in the vector
// they are connected, but elements 0 and 1 in the vector are not

Players will type N, S, E or W to move to a new Location from the currentLocation. If they type an unavailable option, say W while in "a deep, dark cave", they should just stay where they are. When they reach the exit ("the surface"), the game should end.

An input of S N E N E S W, or any other valid sequence of moves to reach the surface, should play the entire game without you (or me) having to enter the inputs room by room.

This behavior should happen naturally if you use cin >> charVariable to get your input.

Tip: write code to build the map first. Then use the debugger to check that it is correct before you add the game loop.