- 首页 >> Algorithm 算法
Revision 2
Software Development with C++ - Assignment 1 Page 1 of 13
Software Development with C++
Assignment 1
Dungeon Crawler
The assignment will require you to design, implement, test, and debug a text-based Roguelike dungeon crawler
game using object-oriented methods and the application of appropriate design patterns. In addition, it will
require to document your classes appropriately using Doxygen comments. The work in this assignment is to be
performed in groups of 4–5 and will be submitted via Cloud Campus in week 17. Please refer to the Cloud
Campus website for exact due dates and times.
Learning Outcomes
After completing this assignment, you will have learnt to:
• Design a class hierarchy using UML
• Apply Object-Oriented principles (encapsulation, reuse, etc.) and Design Patterns to the software design
• Implement the software design in C++ using class inheritance and polymorphism features
• Write well-behaved constructors and destructors for C++ classes
• Use C++ pointers (including smart pointers) and dynamic memory allocation and management
• Use stream I/O and manipulators for formatted input and output
• Write code adhering to coding standards, guidelines and good programming practices
Task Description
Roguelike Dungeon Crawler games are a genre of game that exhibit features typically attributed to the 1980s
computer game Rogue1
. In general, the goal of a Roguelike game is to clear a dungeon, level-by-level, until the
final level is completed. Common features of a Roguelike game include:
1. procedurally generated dungeons,
2. character creation,
3. randomised items and weapons,
4. permanent death, and
5. a variety of creatures to fight that get progressively more difficult deeper into the dungeon.
In this assignment, you will complete Features 1 and 2 from the above list. You will design and implement a
simple text-based Roguelike Dungeon Crawler game that fulfils the following specification. The assignment will be
driven by a text-based menu interface.
The aim of the assignment is to allow you to practise creating an object-oriented design and implementing it in
C++ using the features learnt so far: class inheritance and polymorphism, dynamic memory allocation, and smart
pointers. The focus of the assignment is on identifying and applying appropriate Design Patterns to help develop
the game in such a way that components are easily reusable and extensible.
1 https://en.wikipedia.org/wiki/Rogue_(video_game)
Revision 2
Software Development with C++ - Assignment 1 Page 2 of 13
First, you need to develop a class design using UML class diagrams based on the requirements in the remainder
of this specification. The UML class diagram must include all classes, public data members, public member
functions, protected data members and member functions (if any), and associations between classes.
For this assignment the game has been simplified. Some of the underlying elements (such as the basic menu
interface code) will be provided to get you started. The provided code will be incomplete and may need to be
modified to fit your class design. Parts of the provided code that must not be modified will be marked as such.
You will then need to implement the rest of the game according to the specifications and your design.
A brief example of how the game will be played is provided below. The remainder of the section describes the
requirements of the game in more detail.
> dungeon_crawler.exe
Welcome to Ashes of Software Development: Rite of Passage!
Developed by Matt Selway
COMP 3023 Software Development with C++
*Press any key to continue*
> [Enter]
What would you like to do?
(p)lay the game
> p
You need to create a character... what is your name?
> Dungeon Crusher
Welcome Dungeon Crusher, you have *6* stat points to allocate.
A high Strength stat will boost your damage in combat.
How many points do you want to add to your Strength?
> 3
You have *3* stat points remaining.
A high Dexterity stat will increase your ability to dodge creature attacks.
How many points do you want to add to you Dexterity?
> 2
You have *1* stat point remaining.
A high Wisdom stat will boost the effectiveness of magical items.
How many points do you want to add to your Wisdom?
> 1
*** Character Summary ***
Dungeon Crusher
Strength: 4
Dexterity: 3
Wisdom: 2
Health: 50 / 50
Damage: 10 – 10
Dodge: 20%
Weapon: you look down at your fists and shrug, "these will do"
Item: you look into your backpack, emptiness looks back.
if only you had something to put in it.
While roaming the country side you encounter a strange fork in the road.
To the left lies a dark cave, the foul stench of rotting flesh emanates from it.
To the right is a mysterious tower, a strange magical energy lights the path.
What would you like to do?
Go left: create a (b)asic dungeon
Go right: create a (m)agical dungeon
Go (b)ack the way you came (return to main menu)
> l
You enter the dark cave and see...
Revision 2
Software Development with C++ - Assignment 1 Page 3 of 13
A dark and empty chamber.
To the NORTH you see an opening to another chamber.
To the SOUTH you see the entrance by which you came in.
What would you like to do?
Go (n)orth
Go (b)ack the way you came
View your (c)haracter stats
Return to the main (m)enu
> m
After exploring *0* levels, you run out of the cave as quick as your legs can carry you.
As you emerge from the cave you are startled by the bright light and pause while your eyes
What would like to do?
(p)lay the game
> q
*Are you sure you want to quit? (y/n) *
> y
Note: the following conventions will be used when illustrating example output:
• a ‘>’ at the beginning of a line indicates the command line prompt
• bold orange text indicates input entered by the user
• user input surrounded in square brackets ‘[…]’ indicates a specific key press
• hitting [Enter] after other input is implied
In order to complete this assignment, it is important that you take a planned approach to the assignment. You will
need to think about how to break down the assignment into smaller chunks of functionality that can be
implemented and tested one at a time. Working in an incremental manner, and testing as you progress, helps to
limit errors.
This assignment should be completed in the following stages:
1. Read the assignment specification (more than once)
2. Ensure you understand the 2 design patterns
3. Design a class hierarchy using UML class diagrams that addresses the requirements and applies the 2
design patterns to the game appropriately. Note: the design does not have to be perfectly complete from
the outset, you can revise it as you progress through the assignment. However, it is good to start by
conceptualising your approach before diving into the implementation.
4. Implement character generation—refer to section Player Character
5. Implement the basic dungeon: walls and doors, no creatures nor items (standardised layout)—refer to
section Dungeon (Rooms, Walls, Doors)
6. Implement dungeon navigation: at this point you should be able to play the game and transition between
rooms and dungeon levels without combat—refer to sections Dungeon (Rooms, Walls, Doors) and
General Gameplay
As you implement the functionality, you should tick, highlight, or otherwise mark the requirements that you have
completed. This will help you keep track of your progress and ensure you have addressed all the requirements in
your submission.
Revision 2
Software Development with C++ - Assignment 1 Page 4 of 13
General Gameplay
The gameplay state will be controlled by a Game object. There can only ever be one game in play at one time.
The game allows a player character to explore a dungeon of your choice, room-by-room.
When the game is first started, a welcome message will be displayed and the user will be given the option to play
the game or quit from the main menu.
If the user chooses to quit, the game will prompt the user to confirm that they want to quit the game:
• If the user selects ‘yes’, the game will end.
• If the user selects ‘no’, the game will return to the main menu.
If the user chooses to play the game (from the main menu), the game will prompt the user to create a character.
Refer to section Player Character for details on character creation.
After the user has created their character, the game will prompt the user for the type of dungeon they would like
to explore. In this assignment, there is only one type of dungeon: a “basic” dungeon. Refer to section Dungeon
(Rooms, Walls, Doors) for details on the types of dungeon and their construction.
Once the user selects a dungeon type, the game must create the first dungeon level according to the selected
type, place the character in the first room, display the room’s description, and prompt the user for the next
action. The user can take various actions depending on the configuration of the current room. The following
actions must be supported, as appropriate:
• Move the character to the next room: North, South, East, or West
• Move the character to the previous room (whether this is North, South, East, or West depends on the
door the user “came through”)
• Return to the main menu
In most cases, after a choice is made, the action menu is displayed again.
If the user chooses to move to another room, the current room will be updated to the room that was selected,
the new room’s description will be displayed, and the user prompted for the next action.
If the user chooses to return the main menu, the current dungeon and character will no longer be playable, i.e.,
a new character will have to be created. Therefore, the user must be warned that progress will be lost and
prompted for confirmation. If the user confirms their intent to return to the main menu, the number of dungeon
levels successfully completed must be displayed followed by the main menu.
Once the user reaches the final room of the dungeon the door to the next level will be revealed. If the user
chooses to go through that door (via the appropriate direction, North, South, East, or West), the game will return
the user to the main menu. If the user chooses to play the game (again), a new dungeon level must be built (of
the currently selected dungeon type) but the existing character will be used.
General Requirements
At any time a valid character exists, the user must be able to view their character details (stats, items, etc.). After
viewing the character details, the user will be able to view the weapon specific details, the item specific details, or
return to the main menu.
All user inputs must be validated. If an invalid input is given, a warning must be displayed to the user and the
menu options redisplayed.
Revision 2
Software Development with C++ - Assignment 1 Page 5 of 13
All classes must have appropriate constructors and destructors.
All objects that can be described must be able to be output to a stream using the stream output operator ‘<<’.
Player Character
The player character is represented by the Character class. This class will maintain the state regarding the
player’s character as well as define behaviours appropriate to the character (i.e., update the game state as
appropriate based on the character’s actions).
A character has a name (provided by the player), a combination of static properties and dynamic properties that
may affect the gameplay and the character’s actions, a weapon, and an item. When the player chooses the
option, the character’s stats must be displayed.
The properties are defined at character creation and include:
• Strength—allowable values 1-6, each value > 1 contributes to the damage of the character
• Dexterity—allowable values 1-6, each value > 1 contributes to the dodge chance of the character
• Wisdom—allowable values 1-6, each value > 1 contributes to the effects of magical items
The dynamic properties are derived from various sources and must be updated as appropriate. They include:
• Health points—starts at 50.
Character Creation
Before the game can be played, a character must be created by the user. Creating a character requires the user to
specify some parameters of their character. These include the name of the character and the allocation of points
to the static properties: Strength, Dexterity, and Wisdom.
The game will first prompt the user to enter the character’s name.
The game will then prompt the user to allocate the points the three static properties. The rules for allocating stats
are as follows:
• The user will start with 6 points to allocate
• The user will select the number of points to allocate to each property in turn: 1) Strength, 2) Dexterity, 3)
• The selected number of points will be added to the base value of 1; the resulting value will be assigned to
that property of the Character object.
• The selected number of points cannot exceed 5, so that the total value of the property does not increase
beyond the maximum of 6 points.
• Zero points can be selected if desired, in which case the value of the property will remain the base value.
• After the user selects a valid number of points, the selected number will be subtracted from the number
of available points.
• When selecting the number of points to assign to subsequent properties, the current number of available
points cannot be exceeded.
• After the user has selected the number of points to assign to each property there should be no more
points available. If there are remaining points to be allocated, the game must prompt the user to confirm
that they did not want to assign all the points. If the user indicates that they wish to continue assigning
points, the game will go back to assigning points to each property in turn with the current available
• The game must not allow the value of a static property to exceed the maximum value of 6.
Revision 2
Software Development with C++ - Assignment 1 Page 6 of 13
After the user has allocated all points, or indicated that they do not want to assign the remaining points, the
character description and stats must be displayed to the user. This is the same description that would be
displayed if the user chose to display their character details from the menu.
Character Details Display
When displaying the character details, the following must be included:
• The character’s name
• Strength
• Dexterity
• Wisdom
• Health: current and maximum
After displaying the character details, the menu will allow the user to return to the main menu. These options will
not be available when the character details are being displayed for the first time immediately following character
Dungeon (Rooms, Walls, Doors)
A dungeon level consists of a connected set of rooms and are to be represented by the Dungeon class. Each room
of a dungeon (represented by the Room class) must be identifiable by a number (integer) so that they can be
retrieved from the dungeon object using the numeric identifier. Each room has 4 directions: North, South, East,
and West. In each of these directions, there may be a wall (the Wall class) or a door (the Door class). Doors are
connected to adjacent rooms via a door in the opposing direction. For example, if a room has a door to the north,
the northern room has a door to the south.
Doors are connected to each other to allow movement between rooms in both directions. There are two
exceptions: the entrance to the dungeon level, and the exit. When the user chooses to go through the dungeon
entrance, they will be returned to the main menu as if they chose the option to return to the main menu, that is
they will lose their progress and the dungeon and character will have to be recreated according to the General
Gameplay section. When the user chooses to go through the exit door, they will be returned to the main menu
ready to continue to the next dungeon level as described in the General Gameplay section.
Door objects must be connected to one another using bare pointers in C++.
When the user enters a room, a description of that room must be provided to the user. The description includes
what the room “looks like” (this is up to you, or you can use the text of the examples) and what the character
“sees”, that is, where the doors are located. Descriptions of walls may be included.
When a dungeon level is being created, various elements must be selected randomly including: the type of room.
The size of the dungeon (i.e., the number of rooms) and the connections between rooms will not be randomly
generated. When making a random selection, a simple even weighting between choices can be used. Moreover, it
is not required to do any complex registration of types: a simple switch statement will be acceptable.
Dungeon Types
You must implement one dungeon type: a basic dungeon (BasicDungeon class). Each dungeon type can contain
different types of rooms, walls, and doors.
The basic dungeon is built out of the following:
• Rock room—A dark and empty chamber (Room type)
• Quartz room—The chamber glitters like a thousand stars in the torchlight (Room type)
Revision 2
Software Development with C++ - Assignment 1 Page 7 of 13
• Basic Wall—Out of the darkness looms a jagged formation of rock: you cannot go that way (Wall type)
• Open Doorway—… you see an opening to another chamber (Door type)
The Standard Dungeon Level
To simplify the assignment and make it easier to test and mark, you are not required to implement randomly
generated dungeon levels. Some elements of the dungeon are still randomised, for example, the type of each
room. The structure of the (first) dungeon level must conform to the standard structure defined below. There is
no constraint on the structure of dungeon levels after the first.
In the layout diagram the following symbols are used:
• Large green rectangles represent rooms with the numbers indicating their ID
• Small blue bars joining rooms represent connected pairs of doors
• Entrance and Exit are labelled and indicated by a directional arrow
• Orange smiley faces represent creatures (irreleveant for assignment 1)
• Yellow suns represent consumable items or weapons (irreleveant for assignment 1)
The basic menu structure will be provided for you, but you will need to implement the interactions with the Game
and the transitions between menus for the different contexts, for example, the main menu to the action menu
while playing the game. You are quite free to implement the menu as you desire, that is, the format and text
descriptions of the menu does not have to exactly match the output examples provided. However, the values
entered to perform specific functions must match the following specification to ensure consistency and support
testing/marking. Note: it should not matter if the typed character is uppercase or lowercase.
If in doubt, refer to the provided ‘input script’, which is a series of text input which can be fed automatically to the
application to test the game, and the reference implementation executable.
Revision 2
Software Development with C++ - Assignment 1 Page 8 of 13
Command Character Command Character Command Character
Main Menu Dungeon Selection Menu Action Menu
Play game p Basic Dungeon b Go North n
c Magical
m Go East e
Quit q Go back/Return r Go South s
Character Details Menu Combat Menu Go West w
Weapon Details w Go back b Pick-up Item p
Item Details i Attack a Compare Items o
Previous Menu m Use Item i Use Item i
Use Special
l Use Special
c Character
Main Menu m Main Menu m
Note: Menu commands that are not relevant for assignment 1 have been crossed out.
Your code must be documented appropriately using Doxygen comments. Comment blocks must be used in your
header file to document your classes and class members. Private members should also be documented when it is
not obvious for what they are used—but first check if the code can be improved as clean code is better than
comments. Use comments sparingly in source files, document blocks of code (switch statements, if else groups,
loops, etc.) rather than individual statements: do not comment individual statements, unless the outcome of the
statement is not obvious. Optionally, you can add comments to ‘main.cpp’ to document the ‘main page’.
Code Style
You must write you code conforming to the code style set for this course.
See http://codetips.dpwlabs.com/style-guide
Implementation Rules and Hints
Your initial UML class design may be incomplete or incorrect. Your first design should attempt to cover the major
requirements, in particular the identification of the 2 design patterns. Do not worry if you need to revise and
refactor the design as you progress through the assignment.
It is a good idea to commit the source file (but not the PNG or PDF) of your UML class design to version control.
This will allow you to track the evolution of your design as you progress through the assignment.
It is recommended that you test individual components as you go, rather than trying to test the whole application
through the menu-driven interface. Writing code to test specific elements will speed up development as you will
not need to constantly enter data through the menu interface.
Be sure to check for null pointers before attempting to use an object through a pointer and reset pointers to null
where appropriate.
The game will need to keep track of (at least) the current room, the character, and the previous room/door.
Revision 2
Software Development with C++ - Assignment 1 Page 9 of 13
Ensure you have considered similarity between classes so that you can achieve reuse through inheritance where
appropriate. Also, remember to program to an interface not and an implementation. For example, if you have
related classes but only some have particular data members and you want to ensure substitutability, you can
define an interface on a base class using virtual functions that the derived classes then override appropriately.
The derived classes that do not have those particular data members may then rely on a suitable default
implementation that does not use those data members.
Consider when and where it is appropriate to use smart pointers vs. bare pointers and the effect this choice may
have on constructors, destructors, etc. In most cases the choice is up to you with the exception of the connection
between two doors, doors must be connected via bare pointers.
Smart Pointers – the Dungeon class uses the smart pointer std::shared_ptr to store and retrieve the
rooms (among other things). You must use the std::make_shared() template function to create
the rooms to pass to the function Dungeon::addRoom. The below code snippet is an example of adding a room to
a dungeon:
Dungeon &d = Dungeon{};
d.addRoom(std::make_shared(/* constructor arguments go here */));
The Dungeon and Room classes may not be the only occurrence of smart pointers in your implementation.
Casts – in your code, casts should only need to be performed between a base class pointer and a derived class.
When doing so, a dynamic cast should be performed (using dynamic_pointer_cast). For example, to cast
an Item pointer to a Weapon pointer you would use the following code snippet:
std::shared_ptr item = …; // Wherever the value comes from
std::shared_ptr weapon = std::dynamic_pointer_cast(item);
Type defines – if you know what you are doing, you may define type aliases for the shared pointer types for use in
the MenuInterface and your classes.

Revision 2
Software Development with C++ - Assignment 1 Page 10 of 13
Submission Details
You must submit your complete Qt Creator project folder inside a single zip file. The zip file must include all
source files required to compile and run your program (including a Doxygen config file) as well as your version
control directory: e.g., if using git you must ensure the ‘.git’ folder is present in the zip file. It must not include any
generated or extraneous files such as the ‘*.pro.user’ file—the UML image file is the one exception to the no
generated files rule. Place your UML class diagram in your zip file. Your diagram must be submitted in PNG or PDF
Once you have created the zip file according to the specifications, you are required to upload it to the Assessment
Item 1: Assignment submission via CloudCampus.
Marking Criteria
Your code will be inspected for style – remember consistency is the primary goal of all style guides, the easier it is
to understand your code, the easier it is to allocate marks.
Note: the criteria with negative marks are penalties that will be applied if the submission does not meet the
expected criteria. They are structured such that an otherwise perfect submission will be unable to receive an HD if
and only if the full penalties are applied.
Criteria Mark
Correct identification and use of the design patterns: —
• Singleton 10
• Builder 10
Correct use of inheritance 10
Correct separation of code in header and source files: declaration vs. definition 5
Correct implementation of classes: constructors/destructors, data members, member functions, public/private
Correct use of (bare) pointers and smart pointers 10
Correct implementation of functional requirements: —
• General gameplay 15
• Player Character 15
• Dungeon Creation 10
• Menu Interface 5
Inappropriate use of version control (-5)
Source code does not follow style guide (-5)
Inadequate/inappropriate use of comments (Doxygen) (-5)
Total Possible Marks 100
Revision 2
Software Development with C++ - Assignment 1 Page 11 of 13
Appendix 1: Design Patterns
In developing the class design for the Dungeon Crawler game, the following the Design Patterns must be
• Singleton
• Builder
This section provides brief descriptions of each relevant design pattern in turn. For more information refer to the
book from which these summaries are derived:
Gamma, E, Helm, R, Johnson, R and Vlissides, J 1995, Design patterns: elements of reusable object-oriented
software, Addison-Wesley, ISBN: 978-0-201-63361-0. Be aware that the C++ examples from the book are for an
older version of C++. If using them for guidance, they must be updated to C++ 14.
Adequate descriptions of the above patterns along with some code examples can also be found on Wikipedia:
• Singleton: https://en.wikipedia.org/wiki/Singleton_pattern
• Builder: https://en.wikipedia.org/wiki/Builder_pattern
The Singleton pattern addresses the problem of ensuring that a class has only one instance. Moreover, the one
instance is easily accessible but in a controlled fashion. Such a pattern arises in situations where a single, globally
accessible interface to a system or subsystem is required and, hence, is often used with other patterns such as
Façade and Abstract Factory. An example of singleton a singleton is an application wide configuration. Rather
than parsing the configuration file multiple times and storing multiple copies in memory, the configuration file
should be read once and stored once. Moreover, since various parts of the application may need to access
different settings, the configuration should be globally accessible to ensure the configuration is accessible when
needed. Other examples include: a single print spooler governing access to the printer resources, a single
thread/connection pool handing out connections or threads to clients that request them, etc.
When to Use
The Singleton pattern should be applied to a class when:
1. Exactly one instance of the class must exist
2. A well-known access point to the instance is required
In general, the extensibility of a Singleton through subclassing should also be considered. It will not be required
for this assignment; however, it is important to note as a common criticism of the Singleton pattern is that it
becomes tied to implementation and makes testing difficult due to the inability to replace the singleton instance
with a mock (i.e., a test specific class that is not a complete implementation).
General Structure
A simple representation of the Singleton pattern includes only a Singleton class, i.e., the class that should be a
Singleton, containing: a static member function instance() that returns the unique instance of the class, a
hidden constructor, and a static data member to hold the unique instance of the class.
+ static instance()
- Singleton()
- static theInstance
return theInstance;
Revision 2
Software Development with C++ - Assignment 1 Page 12 of 13
Note the ‘+’ indicates public accessibility and ‘-‘ indicates private accessibility. If considering extensibility of the
Singleton through subclassing, the constructor should be protected rather than private.
Implementation Hints
In C++, the compiler may generate some constructors and operators for you. Ensure you prevent the Singleton
from accidentally being copied or assigned in ways you do not intend by deleting any automatically generated
members that you do not need.
In C++, the static data member can be implemented in two different ways: within the scope of the class or within
the scope of the function. Consider the consequences of each approach and justify your implementation choice in
your comments.
The purpose of the Builder pattern is to separate the representation of a complex object from the process used to
construct it. Further, such separation allows different representations to be constructed from the same process.
For example, a Parser using a Builder to construct a parse tree in different systems: the recognition of the syntax
is handled by the parser, which calls the builder to create the appropriate parse nodes and retrieves the final
parse tree from the Builder once the parsing is complete. The different representations may or may not be
related, for example, an executable parse tree of the parsed syntax, a parse tree for another language (such as in
code transformation), or a composition of widgets for visualising the text processed by the Parser.
An important aspect of the Builder pattern that differentiates it from other creational patterns is that it supports
the creation of complex objects in a step-by-step process, rather than all-at-once.
When to Use
The Builder pattern should be applied when:
• the construction process is, or should be, independent of the object, its parts, and the way that it is
• the construction process should allow for different representations to be created.
Note that there does not always have to be multiple representations, only that multiple representations are
possible. One of the motivations for good design is to support future change more easily.
General Structure
The Builder pattern contains several interacting classes, including:
• the Director, which represents the entity that requires the object to be constructed and ‘directs’ the
Builder to construct it;
• the Builder, which specifies an abstract interface for constructing any Product object, this may include
many different member functions for constructing different types of parts;
Revision 2
Software Development with C++ - Assignment 1 Page 13 of 13
• one or more ConcreteBuilders, which create specific Products from its parts by implementing the