C# Programming Our Battleship game needs several different kinds of ship – we ne
ID: 3588545 • Letter: C
Question
C# Programming
Our Battleship game needs several different kinds of ship – we need a type to store the ships and information about it.
Create a base class called Ship.
Create child classes for each of the ship types in the game (https://en.wikipedia.org/wiki/Battleship_(game)#Description) that inherit from Ship.
Ships should have the following properties:
A private array of positions
A Position is composed of an X and Y coordinate – you should create a struct to encapsulate this.
A read-only length
The constructor for each inherited type should set this to the correct length for the ship type.
A read-only color to be drawn in
The constructor for each inherited type should set this to a different ConsoleColor for drawing.
A flag called Sunk
This should default to false for all ships.
A property called IsBattleship
This property should be overridden by each child type. Only the BattleShip should return true.
A method called Reset
This method should reset the members to their empty defaults
A method called Place(Position start, Direction direction)
Direction should be an enumeration of either Horizontal or Vertical.
This will complete the Position array with the set of coordinates that the ship is covering. E.g., place (new Position(1, 1), Direction.Horizontal) on a patrol boat will fill the array with the points (1, 1) and (2, 1).
Notes:
This is a separate program from previous weeks’. You do not need to consider or implement anything to do with the grid or guessing.
You should choose the correct types and access modifiers for each type.
Create a test program that can run code such as the following:
AircraftCarrier ac = new AircraftCarrier();
Console.WriteLine(ac.IsBattleShip);
ac.Place(new Position(1, 1), Direction.Horizontal);
ac.Reset();
You should write additional code to test all of the methods and ship types.
Given that the positions array is private, how can you test that the values are correct?
Explanation / Answer
Hope following program helps...
------------------------------------------------------------------------
void display (void) {
printf ("XXXXX XXXX XXXXXX XXXXXX XX XXXXXX XXXXX XX XX XX XXXX ");
printf ("XX XX XX XX XX XX XX XX XX XX XX XX XX XX ");
printf ("XXXXX XX XX XX XX XX XXXX XXXX XXXXXX XX XXXX ");
printf ("XX XX XXXXXX XX XX XX XX XX XX XX XX XX ");
printf ("XXXXX XX XX XX XX XXXXXX XXXXXX XXXXX XX XX XX XX ");
printf (" ");
printf ("GAME RULES: ");
printf ("1. This is a two player game. ");
printf ("2. Player 1 is you and Player 2 is the computer. ");
printf ("3. Player 1 will be prompted if user wants to manually input coordinates ");
printf (" for the game board or have the computer randomly generate a game board ");
printf ("4. There are five types of ships to be placed by longest length to the ");
printf (" shortest; [c] Carrier has 5 cells, [b] Battleship has 4 cells, [r] Cruiser ");
printf (" has 3 cells, [s] Submarine has 3 cells, [d] Destroyer has 2 cells ");
printf ("5. The computer randomly selects which player goes first ");
printf ("6. The game begins as each player tries to guess the location of the ships ");
printf (" of the opposing player's game board; [*] hit and [m] miss ");
printf ("7. First player to guess the location of all ships wins ");
}
/**
* Function name : initializeGameBoard ()
* Definition : This function displays initializes values of the multi-
* dimensional array called gameBoard.
* Pre-condition : ROWS & COLS are defined as constant macros
* Post-condition: Array initialize to (~) tilde representing water
*/
void initializeGameBoard (Cell gameBoard[][COLS]) {
int i = 0, j = 0;
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++) {
gameBoard[i][j].symbol = WATER;
gameBoard[i][j].position.row = i;
gameBoard[i][j].position.column = j;
}
}
/**
* Function name : printGameBoard ()
* Usage : printGameBoard (Cell [][], Boolean);
* Definition : This function prints the game board on the console
* screen with an option of showing or not showing the pegs
* Pre-condition : Game board is of Cell struct type and showPegs
if Boolean enum type
* Post-condition: Game board printed on console screen
*/
void printGameBoard (Cell gameBoard [][COLS], Boolean showPegs) {
int i = 0, j = 0;
printf (" 0 1 2 3 4 5 6 7 8 9 ");
for (i = 0; i < ROWS; i++) {
printf ("%d ", i);
for (j = 0; j < COLS; j++) {
if (showPegs == TRUE)
printf ("%c ", gameBoard [i][j].symbol);
else {
switch (gameBoard [i][j].symbol) {
case HIT: printf ("%c ", HIT); break;
case MISS: printf ("%c ", MISS); break;
case WATER:
default: printf ("%c ", WATER); break;
}
}
}
putchar (' ');
}
}
/**
* Function name : putShipOnGameBoard ()
* Usage : putShipOnGameBoard (Cell [][], WaterCraft, Coordinate, int)
* Definition : This function allows you to put the 5 types of ship in the
* the game board specified in the formal argument
* Pre-condition : n/a
* Post-condition: Specific type of ship place on specificied target cell
*/
void putShipOnGameBoard (Cell gameBoard[][COLS], WaterCraft ship,
Coordinate position, int direction) {
int i = ship.length - 1;
for (i = 0; i < ship.length; i++) {
if (direction == HORIZONTAL)
gameBoard [position.row][position.column + i].symbol = ship.symbol;
else /* VERTICAL */
gameBoard [position.row + i][position.column].symbol = ship.symbol;
}
}
/**
* Function name : manuallyPlaceShipsOnGameBoard ()
* Usage : manuallyPlaceShipsOnGameBoard (Cell [][], WaterCraft []);
* Definition : This function allows user to manually place ship on the specified
* gameboard with specific ship
* Pre-condition : Assuming user inputs correct coordinates as it does not check
* if input is correctly inputted
* Post-condition: Ships placed on game board
*/
void manuallyPlaceShipsOnGameBoard (Cell gameBoard[][COLS], WaterCraft ship[]) {
char stringPosition[11] = "";
int i = 0, j = 0;
Coordinate position[5];
Boolean isValid = FALSE;
fflush (stdin);
for (i = 0; i < NUM_OF_SHIPS; i++) {
while (TRUE) {
system ("cls");
printGameBoard (gameBoard, TRUE);
printf ("> Please enter the %d cells to place the %s across (no spaces): ", ship[i].length, ship[i].name);
printf ("> ");
scanf ("%s", stringPosition);
/* convertStringtoPosition returns false if unsuccessful */
if (convertStringtoPosition (position, stringPosition, ship[i].length)) {
isValid = TRUE;
for (j = 0; j < ship[i].length; j++) {
if (gameBoard[position[j].row][position[j].column].symbol == WATER) {
gameBoard[position[j].row][position[j].column].symbol = ship[i].symbol;
} else {
isValid = FALSE;
printf ("> Invalid input! ");
if (j != 0)
while (j >= 0) {
gameBoard[position[j].row][position[j].column].symbol = WATER;
j--;
}
break;
}
}
} else {
isValid = FALSE;
printf ("> Invalid input! ");
}
if (isValid == TRUE) break;
}
}
}
/**
* Function name : randomlyPlaceShipsOnGameBoard ()
* Usage : randomlyPlaceShipsOnGameBoard (Cell [][], WaterCraft []);
* Definition : This function lets the computer randomly place ship on the
* game board
* Pre-condition : n/a
* Post-condition: Ships placed on game board
*/
void randomlyPlaceShipsOnGameBoard (Cell gameBoard[][COLS], WaterCraft ship[]) {
Coordinate position;
int direction = -1;
int i = 0;
for (i = 0; i < NUM_OF_SHIPS; i++) {
while (TRUE) {
direction = getRandomNumber (0, 1); /* 0 -> horizontal, 1 -> vertical */
position = generatePosition (direction, ship[i].length);
if (isValidLocation (gameBoard, position, direction, ship[i].length)) break;
}
putShipOnGameBoard (gameBoard, ship[i], position, direction);
}
}
/**
* Function name : updateGameBoard ()
* Usage : updateGameBoard (Cell [][], Coordinate);
* Definition : This function updates the game board whether
* its a hit or miss
* Pre-condition : n/a
* Post-condition: Game board updated with proper symbol
*/
void updateGameBoard (Cell gameBoard[][COLS], Coordinate target) {
switch (gameBoard[target.row][target.column].symbol) {
/* miss */
case WATER:
gameBoard[target.row][target.column].symbol = MISS;
break;
/* hit */
case CARRIER:
case BATTLESHIP:
case CRUISER:
case SUBMARINE:
case DESTROYER:
gameBoard[target.row][target.column].symbol = HIT;
break;
case HIT:
case MISS:
default:
break;
}
}
/**
* Function name : checkBoundsOfCardinal ()
* Usage : checkBoundsOfCardinal (Boolean [], int, int);
* Definition : This function checks if the specified direction is
* not over the bounds and sets the cardinals with TRUE
* if its within bounds, otherwise FALSE
* Pre-condition : n/a
* Post-condition: Updates the cardinals array
*/
void checkBoundsOfCardinal (Boolean cardinals[], int bound, int direction) {
switch (direction) {
case NORTH:
if (bound < 0)
cardinals[0] = FALSE;
else
cardinals[0] = TRUE;
break;
case SOUTH:
if (bound > 9)
cardinals[1] = FALSE;
else
cardinals[1] = TRUE;
break;
case WEST:
if (bound < 0)
cardinals[2] = FALSE;
else
cardinals[2] = TRUE;
break;
case EAST:
if (bound > 9)
cardinals[3] = FALSE;
else
cardinals[3] = TRUE;
break;
}
}
/**
* Function name : systemMessage ()
* Usage : systemMessage (char *);
* Definition : This function prints a message on the console and awaits
* for user to press the enter key
* Pre-condition : n/a
* Post-condition: n/a
*/
void systemMessage (char *message) {
char ch = '';
do {
printf ("%s", message);
} while ((ch = getch()) != ' ');
}
/**
* Function name : checkSunkShip ()
* Usage : checkSunkShip (shor [][], short, char, FILE *);
* Definition : This function check if a ship has sunk based on the
* how of the length of ship is left. If a ship was sunk
* it is logged on an output file
* Pre-condition : stream to output file was created
* Post-condition: n/a
*/
Boolean checkSunkShip (short sunkShip[][NUM_OF_SHIPS], short player, char shipSymbol, FILE *stream) {
Boolean sunked = FALSE;
switch (shipSymbol) {
case CARRIER:
if (--sunkShip[player][0] == 0) {
printf ("> Player %d's Carrier sunked! ", player + 1);
/* Write to battleship.log */
fprintf (stream, "Player %d's Carrier sunked! ", player + 1);
sunked = TRUE;
}
break;
case BATTLESHIP:
if (--sunkShip[player][1] == 0) {
printf ("> Player %d's Battleship sunked! ", player + 1);
/* Write to battleship.log */
fprintf (stream, "Player %d's Battleship sunked! ", player + 1);
sunked = TRUE;
}
break;
case CRUISER:
if (--sunkShip[player][2] == 0) {
printf ("> Player %d's Cruiser sunked! ", player + 1);
/* Write to battleship.log */
fprintf (stream, "Player %d's Cruiser sunked! ", player + 1);
sunked = TRUE;
}
break;
case SUBMARINE:
if (--sunkShip[player][3] == 0) {
printf ("> Player %d's Submarine sunked! ", player + 1);
/* Write to battleship.log */
fprintf (stream, "Player %d's Submarine sunked! ", player + 1);
sunked = TRUE;
}
break;
case DESTROYER:
if (--sunkShip[player][4] == 0) {
printf ("> Player %d's Destroyer sunked! ", player + 1);
/* Write to battleship.log */
fprintf (stream, "Player %d's Destroyer sunked! ", player + 1);
sunked = TRUE;
}
break;
}
return sunked;
}
/**
* Function name : isValidLocation ()
* Usage : isValidLocation (Cell [][], Coordinate, int, int);
* Definition : This function checks if specified position, direction and
* length is valid on location specified on the game board
* Pre-condition : n/a
* Post-condition: n/a
*/
Boolean isValidLocation (Cell gameBoard[][COLS], Coordinate position,
int direction, int length) {
int i = length - 1;
Boolean isValid = TRUE;
for (i = 0; isValid && i < length; i++) {
if (direction == HORIZONTAL) {
if (gameBoard [position.row][position.column + i].symbol != WATER &&
(position.column + i) < COLS)
isValid = FALSE;
} else { /* VERTICAL */
if (gameBoard [position.row + i][position.column].symbol != WATER &&
(position.row + i) < ROWS)
isValid = FALSE;
}
}
return isValid;
}
/**
* Function name : convertStringtoPosition ()
* Usage : convertStringtoPosition (Cell [], char *, int);
* Definition : This function converts string coordinates into individual
* integer coordinates
* Pre-condition : Assuming that user inputs correct coordinates since program
* does not check for inccorrect coordinates
* Post-condition: n/a
*/
Boolean convertStringtoPosition (Coordinate position[], char *stringPosition, int length) {
Boolean flag = TRUE;
char temp = '';
int i = 0, j = 0, k = 1;
/* checks if length of input is good */
if (strlen (stringPosition)/2 == length) {
/* loops through the length of the ship */
for (i = 0; i < length && flag; i++) {
/* checks if each cell is a digit */
if (isdigit (stringPosition[j]) && isdigit (stringPosition[k])) {
position[i].row = stringPosition[j] - '0';
position[i].column = stringPosition[k] - '0';
j += 2;
k += 2;
} else {
flag = FALSE;
}
}
} else {
flag = FALSE;
}
return flag;
}
/**
* Function name : isWinner ()
* Usage : isWinner (Stats [], int);
* Definition : This function determines if there is a winner based
* on the 17 total pegs for each player
* Pre-condition : n/a
* Post-condition: n/a
*/
Boolean isWinner (Stats players[], int player) {
Boolean isWin = FALSE;
if (players[player].numHits == 17)
isWin = TRUE;
return isWin;
}
/**
* Function name : generatePosition ()
* Usage : generatePosition (int, int);
* Definition : This function generates position based on the
* direction and length specified and it can't be
* more than the game board size
* Pre-condition : n/a
* Post-condition: n/a
*/
Coordinate generatePosition (int direction, int length) {
Coordinate position;
if (direction == HORIZONTAL) {
position.row = getRandomNumber (0, ROWS);
position.column = getRandomNumber (0, COLS - length);
} else { /* VERTICAL */
position.row = getRandomNumber (0, ROWS - length);
position.column = getRandomNumber (0, COLS);
}
return position;
}
/**
* Function name : getTarget ()
* Usage : getTarget ();
* Definition : This function reads a row and column values from
* the user
* Pre-condition : n/a
* Post-condition: n/a
*/
Coordinate getTarget (void) {
Coordinate target;
fflush (stdin);
printf ("> Enter Target (ex. > 3 4): ");
printf ("> ");
scanf ("%d %d", &target.row, &target.column);
return target;
}
/**
* Function name : checkShot ()
* Usage : checkShot (Cell [][], Coordinate);
* Definition : This function checks if the coordinates on the
* game board is a miss, hit, water or water craft
* Pre-condition : n/a
* Post-condition: n/a
*/
short checkShot (Cell gameBoard[][COLS], Coordinate target) {
int hit = -2;
switch (gameBoard[target.row][target.column].symbol) {
/* miss */
case WATER:
hit = 0;
break;
/* hit */
case CARRIER:
case BATTLESHIP:
case CRUISER:
case SUBMARINE:
case DESTROYER:
hit = 1;
break;
case HIT:
case MISS:
default:
hit = -1;
break;
}
return hit;
}
/**
* Function name : getRandomNumber ()
* Usage : getRandomNumber (int, int);
* Definition : This function returns a random number between and
* including the lowest to the highest number
* Pre-condition : n/a
* Post-condition: n/a
*/
int getRandomNumber (int lowest, int highest) {
if (lowest == 0)
return rand () % ++highest;
if (lowest > 0)
return rand () % ++highest + lowest;
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.