Sunteți pe pagina 1din 13

Department of Computer Science

COS110 - Program Design: Introduction


Assignment 1
Copyright
c 2019 by Emilio Singh. All rights reserved.

1 Introduction

Deadline: 12th of August, 12:00

1.1 Objectives and Outcomes


The objective of this assignment is to provide a comprehensive practical exercise that
tests the use of classes, objects, constructors, destructors, dynamic memory and other
associated elements.

1.2 Submission
All submissions are to be made to the assignments.cs.up.ac.za page under the COS
110 page, and for the correct assignment slot. Submit your code to Fitchfork before the
closing time. Students are strongly advised to submit well before the deadline as no
late submissions will be accepted.

1.3 Plagiarism
The Department of Computer Science considers plagiarism as a serious offence. Disci-
plinary action will be taken against students who commit plagiarism. Plagiarism includes
copying someone elses work without consent, copying a friends work (even with consent)
and copying textual material from the Internet. Copying will not be tolerated in this
course. For a formal definition of plagiarism, the student is referred to http://www.ais.
up.ac.za/plagiarism/index.htm (from the main page of the University of Pretoria site,
follow the Library quick link, and then click the Plagiarism link). If you have questions
regarding this, please ask one of the lecturers, to avoid any misunderstanding.

1.4 Implementation Guidelines


Follow the specifications of the assignment precisely. For the assignment, you will be
required to create your own makefile so pay attention to the names of the files you will
be asked to create. If the assignment requires you to submit additional files of your
own, follow the file structure and format exactly. Incorrect submissions will use up your
uploads and no extensions will be given. In terms of C++, unless otherwise stated, the

1
usage of C++11 or additional libraries outside of those indicated in the practical, will
not be allowed. Some of the appropriate files that you submit will be overwritten during
marking to ensure compliance to these requirements. If the specification makes use of text
files, for providing input information, be sure to include blank text files with the specified
names.

1.5 Classes
The class is one of the foundations of the Object Oriented (OO) paradigm. The purpose
of classes is to organise methods and data into logically coherent units that provide can
reusable functionality to building complex programs. Strongly associated with classes,
are their two most recognisable features of a class that allow for creating and destroying
instances of that class.

1.6 Scenario
Battleships is a game that is based on two players taking turns to guess at locations of
ships located on a grid board. Correct guesses damage ships of the opposing player, and
incorrect guesses reflect missed shots. The goal of the game is to correctly sink all of
the enemy’s ships before yours are sunk. For this assignment, you will be implementing
a variation of this game with a number of key gameplay changes ranging from different
style of tokens, to a simultaneous turn resolution mechanic.

1.7 Mark Distribution

Activity Mark
(Task 1) Ship Class 20
(Task 2) Player Class 30
(Task 3) Game Class 40
Total 90

2 Assignment
The assignment is broken up into 3 separate tasks that follow on from each other. In each
task, you will be required to implement code, and design components that will be used
by later tasks to build more complex systems. It is recommended to work sequentially
from Task 1 to Task 3.

2.1 Game Rules


Presented here, is an outline of the rules of the game around which this assignment is
centred. This is not meant to be a completely exhaustive explanation, as you should defer
to the specifics provided in the Task descriptions for more detail, but rather this is to
flesh out the design and intention behind the game.

2
2.1.1 Game Board

The game is played on a square board made of NxN characters where N is a number.
The square board is meant to represent open seas and thus there is no special terrain or
features beyond the ships. The board is numbered of course, with the top leftmost corner
representing the coordinates (0,0). The subsequent rows and columns increase as they
move away from this position.

For example, consider,

01234
0#####
1#####
2#####
3#####
4#####

This is a board made of 5x5 tiles. Each tile represents the open sea and the board
is currently completely empty. The positions of the each tile, in terms of coordinates
it reflects is given by the numbers. The top leftmost corner is (0,0) and the bottom
rightmost corner is (4,4)

2.1.2 Ships and Tokens

Unlike Battleships, this game does not use differently shaped tokens to represent ships
on the board. Instead, a ship is represented by a ∗ symbol whose coordinates represent
the location of the ship on the board. All ships are represented this way, indicating that
there are no specialised tokens for ships.

Both players get an equal number of tokens for the match, and they must place them
on the board. Neither player knows, or should know, where their opponent’s pieces are
placed and thus, both place their tokens on the board ignoring the positions of the other
player’s tokens. In effect, this creates two initially identical boards that then get their
tokens placed on. Tokens belonging to the same player cannot overlap in their placements
on the board; each must be uniquely placed. However, enemy tokens can share.

So Player A cannot have two tokens on position (0,0) but Player A and Player B can
both have one token on (0,0).

2.1.3 Turn Sequences

The game is played in a number of turns. The number of turns is the size of a board
length so a 5x5 board would then have a game consisting of 5 turns. In each turn, both
players will make their guesses for where the enemy ships are on the board. This happens
simultaneously with each player making a number of guesses also equal to the size of the
board length.

So again, a board of 5x5 would have turns where each player makes 5 guesses for where the

3
enemy ships are. After resolving the guesses, feedback about their positions is provided
as well. This would then be used to inform the next turns’ moves.

The game ends when either the turns have elapsed, or one side loses all of their ships. The
winning side is calculated then through a scoring mechanic. As it is possible for the two
sides to destroy each other during a simultaneous turn resolution, there is an additional
scoring mechanic in place that is used to resolve the game.

2.1.4 Example Board

Here is an example 5x5 board with 4 tokens placed.

01234
0*####
1#####
2##*##
3###*#
4#*###

There are no restrictions generally on token placement but it is advisable to try to avoid
a predictable placement such as all of the ships in a straight line.

2.2 Task 1: Ship Class


The basis of the assignment is the Ship class. It is comprised of two files: ship.h and
ship.cpp. You will be required to produce both of these files for yourself. A UML
diagram for the ship class is provided to you below:

ship
-id:string
-value:int
-xCoord:int*
-yCoord:int*
------------------------
+ship()
+ship(newShip:ship*)
+ship(i:string,val:int,x:int,y:int)
+∼ ship()
+getID():string
+getVal():int
+getX():int
+getY():int
+setID(a:string):void
+setVal(a:int):void
+setX(a:int):void
+setY(a:int):void

The class variables are as follows:

4
• id: A unique string id that identifies each of the ships. The ID has the form of a
string with the format of ”(X,Y)” where X is the X coordinate of the ship and Y
the y coordinate of the ship. Since each ship must be uniquely assigned, these ids
are all unique to each player.

• value: A numerical value in the range [0,5) that assigns additional worth to each
ship.

• xCoord: The X coordinate of the ship on the board.

• yCoord: The Y coordinate of the ship on the board.

The class methods have the following behaviour:

• ship: The default and empty constructor for the ship class.

• ship(newShip:ship*): This is a copy constructor for the ship class. It receives an


instantiated ship object and copies the values of that object into a newly constructed
instance.

• ship(i:string,val:int,x:int,y:int): This is a value-based constructor for the class. It


takes 4 separate arguments which all correspond to values inside the class.

• ∼ship: The class destructor. This deallocates any allocated memory of the class.
It also prints out (on a new line), the following message: ”Ship <ID> destroyed”
where <ID> refers to the ID of the ship that is deallocated.

• getID: This returns the ID variable.

• getVal: This returns the value variable.

• getX: This returns the X coordinate variable.

• getY: This returns the Y coordinate variable.

• setID: This sets the ID variable to the passed in value.

• setVal: This sets the value variable to the passed in value.

• setX: This sets the x coordinate to the passed in value.

• setY: This sets the y coordinate to the passed in value.

You are allowed to make use of the following libraries:

• iostream

• string

5
2.3 Task 2: Player Class
The next most important component is the Player class. It is comprised of two files:
player.h and player.cpp. You will be required to produce both of these files for yourself.
A definition for the class is provided below:

player
-score:int
-shipList: ship**
-shipsDeployed:int
------------------------
+player()
+player(score:int,deployed:int)
+player(newPlayer:player*)
+∼ player()
+addShip(newShip:ship*):int
+removeShip(id:string):void
+tallyShips():int
+addToScore(s:int):void
+getScore():int
+getDeployed():int
+getValueOfShip(id:string):int

The variables are defined as follows:

• score: The current score of the player. This is accumulated over a number of turns.
• shipList: A dynamic array of ship objects that reflects all the tokens of the player
left in the game.
• shipsDeployed: The original number of ships that the player had at the start of the
game.

The methods are defined as follows:

• player(): The default constructor for the class.


• player(score:int,deployed:int): This is a value based constructor. It will receive
a number of arguments and supply them to the appropriate variables. It will also
construct the shipList variable but not populate it with values. That is, the variable
should be initialised as an array, but the elements should be set to null.
• player(newPlayer:player*): This is a copy constructor. It receives a player object
and should instantiate a new instance of the class using the provided argument. The
exception is that the shipList should not be directly copied into the new object. It
should be set based on the passed in size, but set to null as in the other constructor.
• ∼player(): This deallocates any allocated memory of the class.
• tallyShips(): This function determines the number of remaining ships left. As ships
are destroyed, their elements in the array are removed and those elements set to
null. This function should return the number of active ships left that the player has.

6
• addShip(newShip:ship*): This function receives a ship object and then adds it to
the current list of ships. The object’s values should be used to create a new instance
of the ship class at the first, from index 0, open space. The function returns the
index of the element where the ship object was created. If the list is full, that is all
spaces are taken, then it should return -1.

• removeShip(id:string): This function removes the ship in the list at the id. It will
deallocate the element, and set it to null. In the event that the id is not found, or
already null, nothing happens.

• addToScore(s:int): A function that adds a provided value to the current player score.

• getScore(): This returns the score value.

• getDeployed(): This returns the number of ships that were originally deployed.

• getValueOfShip(id:string): This function receives the id of a ship, and returns the


value associated with that ship. Should the ship not be found, return 0;

You are allowed to make use of the following libraries:

• iostream

• string

2.4 Task 3: Game Class


The final part of the assignment is the Game class. It is comprised of two files: game.h
and game.cpp. This class is where the bulk of the processing and complexity of the
assignment will be found as implementing it, implements the game logic. You will be
required to produce both of these files for yourself. A UML diagram for the class is
provided to you below:

game
-playerA: player*
-playerB: player*
-numTurns: int
-numTokens: int
-boardLength:int
-boardA: string**
-boardB: string**
-seed:int
------------------------
+game()
+game(a:player *,b:player *,boardName:string, aBoard:string,bBoard:string,seed:int)
+∼ game()
+playGame():void
+getTurns():int
+getLength():int

7
+getBoardAt(x:int,y:int, player:string):string
+createPlayerAFeedback():void
+createPlayerBFeedback():void
+playTurn():void

The variables are defined as follows:

• playerA: The first player of the game.

• playerB: The second player of the game.

• numTurns: The number of turns the game is to be played for. This should be equal
to the length of one board side.

• numTokens: The number of deployable tokens for each player at the start of the
game.

• boardLength: The size of the board as per one of its sides.

• boardA: The game board associated with Player A. It is a 2D matrix of strings.

• boardB: The game board associated with Player B. It is a 2D matrix of strings.

The methods have the following behaviour:

• game(): The default, empty constructor.

• game(a:player *,b:player *,boardName:string, aBoard:string,bBoard:string,seed:int):


This receives two player objects to instantiate the corresponding player variables,
as well as the file name of the board text file. The next two arguments refer to the
placements text files that each player uses to place their tokens at the start of the
game. The last argument is the random seed chosen for the game.

Read in the player boards from both files, and create the respective boards with
their token allocations. Once the tokens are allocated, all of the ships from their
respective boards are assigned to the players. When each ship is added, its value
variable should be set to a random number in the range [0,5).

• ∼game(): The class destructor. This deallocates any allocated memory of the class.
It also prints out (on a new line), the following message: ”Game Over”.

• getTurns(): This returns the number of turns that are going to be played during
the game.

• getLength(): This returns the size of one length of the board.

• getBoardAt(x:int,y:int, player:string): This returns the string value located at the


(x,y) coordinates of the specified player board. The player variable will either be
”A” or ”B” indicating which board to look at when returning values. If the given
values are out of bounds, or the player type is invalid, return ”NA” instead.

8
• createPlayerAFeedback():This function creates a textfile that contains the outcome
of player A’s turn with regards to their guesses. This file is always called feed-
backA.txt and should always overwrite the latest file. The result of the guesses
applied to Player B’s board is the basis of their feedback.

• createPlayerBFeedback(): This function creates a textfile that contains the out-


come of player B’s turn with regards to their guesses. This file is always called
feedbackB.txt and should always overwrite the latest file. The result of the guesses
applied to Player A’s board is the basis of their feedback.

• playTurn(): This is the function that plays the turn for both player A and player B.
The function asks for an input of moves for player A and player B. The convention
for these files will follow the convention of moves<A|B> <X> where <A|B> refers
to A or B and X is the turn number. For example, movesA1.txt is the file of moves
for player A during turn 1. The input looks as follows:

Player A Moves: movesA1.txt


Player B Moves: movesB1.txt

Once the input files are provided, the function, starting with player A, will iterate
through the list of moves and determine the effect of each move. Determining the
effect requires examining the cell indicated by the move. If a ship is found at that
location on the board, it is destroyed and that position is then converted to the X
character. If the guess is a miss, that cell is converted to the O character. In this
way, player A will modify player B’s board and vice versa.

The score of the player who made the move is updated by adding 5 points plus
the value of the ship to the player’s score. Then, the ship is removed from the
appropriate list. This process is repeated until all guesses have been examined for
each player.

• playGame(): This is the overall control function of the game. It will conduct all
of the turns, for each player, as well as check if the game is over. The game ends
when a player has no more ships remaining, or the number of turns has expired.
Therefore, the overall structure of the game is as follows:

– Initialise the board and placement for both players (done during class con-
struction).
– Check if the turn limit has expired.
– Check if one player is out of ships (both can be at the start of a turn)
– If the game is still ongoing, conduct a turn.
– Send the feedback for each player.

When the game is finished, print the following information in the following format:

Player A Score: 20
Player B Score: 12
Player A Wins!

9
Each should be on a new line. You are allowed to make use of the following libraries:

• iostream

• string

• fstream

• sstream

• cstdlib

2.5 File Examples


Provided here are examples of the files that the game will need. These are structural
examples, that show how the files should be composed. You are required to produce your
own files for testing purposes.

2.5.1 Board

3
4

The first line of the file, is the size of the board length. The second line is the number
of tokens per player. The size will not be known beforehand so keep this in mind during
construction of the boards.

2.5.2 Placement

#*#
#*#
##*

Consider the above 3x3 board where player A has placed 3 tokens. Each one is a unique
ship that should be included on their player profile.

2.5.3 Moves

3,4
0,1
4,3
2,3

This is a list of guesses in terms of X and Y coordinates separated by commas. You can
assume that the coordinates will always be valid in some way and that repeats will not
be included.

10
2.5.4 Feedback

#O#
#X#
##O

The above is an example of the feedback file that needs to be produced. The file references
the results of a turn. The X and O symbols refer to hits and misses respectively. The
matrix is reproduced in the textfile as it is for the corresponding player. However, the
position of the remaining enemy ships is not revealed, only the hits and misses.

2.6 Example Run


Presented below, is an example run of the program to give you an example of how the
entire program should function. It is not meant to be indicative of the full totality of the
execution of the program; nor an indicator of program correctness. You still need to test
your code thoroughly.

Given a 3x3 map with the following placements for player A and B and the start of
the game:

A
##*
*##
##*

B
*##
*##
#*#

Consider the following list of guesses for A and B:

A
1,1
2,2
1,0

B
1,2
2,1
0,0

From this, the following feedback files will be produced:

A Feedback -Outcome of their guesses on B’s Board


###
XO#

11
##O

B Feedback -Outcome of their guesses on A’s Board


O##
##O
#O#

2.7 Submission
You will have to submit your code to 3 separate upload slots. You will have a maximum
of 5 uploads per slot for this assignment. The slots are very limited so do not rely on
Fitchfork to debug your code.

2.7.1 Task 1 Checklist

The following files need to be submitted for Task 1 of the assignment:

• ship.h

• ship.cpp

• main.cpp

• makefile

2.7.2 Task 2 Checklist

The following files need to be submitted for Task 2 of the assignment:

• ship.h

• ship.cpp

• player.h

• player.cpp

• main.cpp

• makefile

2.7.3 Task 3 Checklist

The following files need to be submitted for Task 3 of the assignment:

• ship.h

• ship.cpp

• player.h

12
• player.cpp

• game.h

• game.cpp

• main.cpp

• makefile

• input1.txt,input2.txt,input3.txt

• board1.txt,board2.txt,board3.txt

• placeA1.txt,placeA2.txt,placeA3.txt

• placeB1.txt,placeB2.txt,placeB3.txt

• movesA1.txt, movesB1.txt

• movesA2.txt, movesB2.txt

• movesA3.txt, movesB3.txt

• movesA4.txt, movesB4.txt

• movesA5.txt, movesB5.txt

The text files should be blank. These will be replaced during testing.

Be sure to work incrementally and test as you go to ensure that your code is robust
under a number of possible conditions. The very limited number of uploads means that
the margins for error are relatively low and therefore caution is advised. Remember that
while your code might appear to be working, there could be a number of non-obvious
problems under the surface.

13

S-ar putea să vă placă și