In part 1 of this exercise, you will be working as individuals in creating one f
ID: 674484 • Letter: I
Question
In part 1 of this exercise, you will be working as individuals in creating one function to interface with an electronic Battle Ship game:
lastNameAttack(int mode, int opponent) is your main driver function used to attack the opponent's ships. This is where much of the strategy for your program goes. (The other function you implement will be described later.) Depending on the mode, you may be starting a new game (BS_MODE_NEW_GAME), or continuing an existing one (BS_MODE_CONTINUE_GAME). It calls the opponent's incomingFire() function just as the opponent will calls yours (initially you will be using an internally defined function, until you complete part 2 of this assignment). Begin writing your attack function using the following code.
The fire() function you will be calling accepts two arguments:
A capital letter (char) in the range of 'A' .. 'A'+BS_GRID_ROWS-1 that indicates the row in your grid to attack.
An integer (int) in the range of 1 .. BS_GRID_COLS that indicates the column of your grid to attack.
The return code will be:
0 if there is only open water.
The bit BS_SHIP_HIT will be set, or both BS_SHIP_HIT and BS_SHIP_SANK will be set. In addition, the ship that was hit will be indicated in the lowest four bits of the return code. You may use BS_SHIP_MASK to help extract the number for the ship type.
In order to interface properly with Battle Ship, you will need create the file battleship.h and store it in the same folder as your .cpp file created above. Do not copy this code into your .cpp file.
Everywhere in your program code, you must use the symbolic constants defined in battleship.h file where possible. Do not "hard-code" any literal values—they might change, e.g the number of rows or columns for this exercise may be adjusted before recompiling and testing your program. Your implementation should work for any reasonable number of rows or columns.
Milestone submission (part 1)
Create the .cpp file above replacing text with your name where required. Implement your attack() function so that no critical errors occur. Non-critical errors are allowed at this time.
Final submission (part 1)
Implement your attack() function so that no critical, nor non-critical errors occur. You must also implement some intelligence to your program that observes the return code of the opponents fire() function and acts accordingly. You will find you will experience two modes of play:
Searching for any ship (unbounded search): you are unaware of any un-sunk ships
Searching for a specific ship (focused search): you have already hit a ship somewhere, it is not sunk yet, and you need to finish sinking it.
Furthermore, challenge yourself to implement a version that does the best against the professor's code that you are linking with. There will also be an opportunity during lab to compete with other student versions of Battle Ship prior to the part 2 submission date.
Explanation / Answer
#include <iostream.h>
#include <string.h>
const int BOARD_WIDTH = 15;
const int BOARD_HEIGHT = 10;
const int SHIP_TYPES = 5;
const char isWATER = 247; //ASCII Character Code
const char isHIT = 'X';
const char isSHIP = 'S';
const char isMISS = '0';
struct POINT {
//A location on the grid defined
//by X(horizontal) Y(vertical) coordinates
int X;
int Y;
};
struct SHIP {
//Ship name
string name;
//Total points on the grid
int length;
//Coordinates of those points
POINT onGrid[5]; //0-4 max length of biggest ship
//Whether or not those points are a "hit"
bool hitFlag[5];
}ship[SHIP_TYPES];
struct PLAYER {
char grid[BOARD_WIDTH][BOARD_HEIGHT];
}player[3]; //Ignore player 0, just using player's 1 & 2
enum DIRECTION {HORIZONTAL,VERTICAL};
struct PLACESHIPS {
DIRECTION direction;
SHIP shipType;
};
bool gameRunning = false;
//Functions
void LoadShips();
void ResetBoard();
void DrawBoard(int);
PLACESHIPS UserInputShipPlacement();
bool UserInputAttack(int&,int&,int);
bool GameOverCheck(int);
int main()
{
LoadShips();
ResetBoard();
//"PLACE SHIPS" phase of game
//Loop through each player...
for (int aplyr=1; aplyr<3; ++aplyr)
{
//Loop through each ship type to place
for (int thisShip=0; thisShip<SHIP_TYPES; ++thisShip)
{
//Display gameboard for player
system("cls");
DrawBoard(aplyr);
//Give instructions
cout << " ";
cout << "INSTRUCTIONS (Player " << aplyr << ") ";
cout << "You are about to place your ships. Format should be: ";
cout << "Facing (0:Horizontal,1:Vertical), X (top-row) coords, Y (left-side) coords ";
cout << "Example: 0 7 2 This would place a ship beginning at X:7 Y:2 going horizontal ";
cout << "Ship to place: " << ship[thisShip].name << " which has a length of " << ship[thisShip].length << " ";
cout << "Where do you want it placed? ";
//Get input from user and loop until good data is returned
PLACESHIPS aShip;
aShip.shipType.onGrid[0].X = -1;
while (aShip.shipType.onGrid[0].X == -1)
{
aShip = UserInputShipPlacement();
}
//Combine user data with "this ship" data
aShip.shipType.length = ship[thisShip].length;
aShip.shipType.name = ship[thisShip].name;
//Add the FIRST grid point to the current player's game board
player[aplyr].grid[aShip.shipType.onGrid[0].X][aShip.shipType.onGrid[0].Y] = isSHIP;
//Determine ALL grid points based on length and direction
for (int i=1; i<aShip.shipType.length; ++i)
{
if (aShip.direction == HORIZONTAL){
aShip.shipType.onGrid[i].X = aShip.shipType.onGrid[i-1].X+1;
aShip.shipType.onGrid[i].Y = aShip.shipType.onGrid[i-1].Y; }
if (aShip.direction == VERTICAL){
aShip.shipType.onGrid[i].Y = aShip.shipType.onGrid[i-1].Y+1;
aShip.shipType.onGrid[i].X = aShip.shipType.onGrid[i-1].X; }
//Add the REMAINING grid points to our current players game board
player[aplyr].grid[aShip.shipType.onGrid[i].X][aShip.shipType.onGrid[i].Y] = isSHIP;
}
//Loop back through each ship type
}
//Loop back through each player
}
//********* FINISHED WITH "PLACE SHIPS" PHASE *********************************
//*****************************************************************************
//Ready to play the game
gameRunning = true;
int thisPlayer = 1;
do {
//Because we are ATTACKING now, the
//opposite players board is the display board
int enemyPlayer;
if (thisPlayer == 1) enemyPlayer = 2;
if (thisPlayer == 2) enemyPlayer = 1;
system("cls");
DrawBoard(enemyPlayer);
//Get attack coords from this player
bool goodInput = false;
int x,y;
while (goodInput == false) {
goodInput = UserInputAttack(x,y,thisPlayer);
}
//Check board; if a ship is there, set as HIT.. otherwise MISS
if (player[enemyPlayer].grid[x][y] == isSHIP) player[enemyPlayer].grid[x][y] = isHIT;
if (player[enemyPlayer].grid[x][y] == isWATER) player[enemyPlayer].grid[x][y] = isMISS;
//Check to see if the game is over
//If 0 is returned, nobody has won yet
int aWin = GameOverCheck(enemyPlayer);
if (aWin != 0) {
gameRunning = false;
break;
}
//Alternate between each player as we loop back around
thisPlayer = (thisPlayer == 1) ? 2 : 1;
} while (gameRunning);
system("cls");
cout << " CONGRATULATIONS!!! PLAYER " << thisPlayer << " HAS WON THE GAME! ";
system("pause");
return 0;
}
bool GameOverCheck(int enemyPLAYER)
{
bool winner = true;
//Loop through enemy board
for (int w=0; w<BOARD_WIDTH; ++w){
for (int h=0; h<BOARD_HEIGHT; ++h){
//If any ships remain, game is NOT over
if (player[enemyPLAYER].grid[w][h] = isSHIP)
{
winner = false;
return winner;
}
}}
//If we get here, somebody won, game over!
return winner;
}
bool UserInputAttack(int& x, int& y, int theplayer)
{
cout << " PLAYER " << theplayer << ", ENTER COORDINATES TO ATTACK: ";
bool goodInput = false;
cin >> x >> y;
if (x<0 || x>=BOARD_WIDTH) return goodInput;
if (y<0 || y>=BOARD_HEIGHT) return goodInput;
goodInput = true;
return goodInput;
}
PLACESHIPS UserInputShipPlacement()
{
int d, x, y;
PLACESHIPS tmp;
//Using this as a bad return
tmp.shipType.onGrid[0].X = -1;
//Get 3 integers from user
cin >> d >> x >> y;
if (d!=0 && d!=1) return tmp;
if (x<0 || x>=BOARD_WIDTH) return tmp;
if (y<0 || y>=BOARD_HEIGHT) return tmp;
//Good data
tmp.direction = (DIRECTION)d;
tmp.shipType.onGrid[0].X = x;
tmp.shipType.onGrid[0].Y = y;
return tmp;
}
void LoadShips()
{
//Sets the default data for the ships
//we plan to include in the game
//IMPORTANT!! > MUST MATCH SHIP_TYPES -Default=5 (0-4)
ship[0].name = "Cruiser"; ship[0].length = 2;
ship[1].name = "Frigate"; ship[1].length = 3;
ship[2].name = "Submarine"; ship[2].length = 3;
ship[3].name = "Escort"; ship[3].length = 4;
ship[4].name = "Battleship"; ship[4].length = 5;
}
void ResetBoard()
{
//Loop through each player
for (int plyr=1; plyr<3; ++plyr)
{
//For each grid point, set contents to 'water'
for (int w=0; w<BOARD_WIDTH; ++w){
for (int h=0; h<BOARD_HEIGHT; ++h){
player[plyr].grid[w][h] = isWATER;
}}
//Loop back to next player
}
}
void DrawBoard(int thisPlayer)
{
//Draws the board for a player (thisPlayer)
cout << "PLAYER " << thisPlayer << "'s GAME BOARD ";
cout << "---------------------- ";
//Loop through top row (board_width) and number columns
cout << " ";
for (int w=0; w<BOARD_WIDTH; ++w) {
if (w < 10)
//Numbers only 1 character long, add two spaces after
cout << w << " ";
else if (w >= 10)
//Numbers 2 characters long, add only 1 space after
cout << w << " ";
}
cout << " ";
//Loop through each grid point and display to console
for (int h=0; h<BOARD_HEIGHT; ++h){
for (int w=0; w<BOARD_WIDTH; ++w){
//If this is the FIRST (left) grid point, number the grid first
if (w==0) cout << h << " ";
//If h was 1 character long, add an extra space to keep numbers lined up
if (w<10 && w==0) cout << " ";
//Display contents of this grid (if game isn't running yet, we are placing ships
//so display the ships
if (gameRunning == false) cout << player[thisPlayer].grid[w][h] << " ";
//Don't show ships, BUT show damage if it's hit
if (gameRunning == true && player[thisPlayer].grid[w][h] != isSHIP)
{cout << player[thisPlayer].grid[w][h] << " ";}
else if (gameRunning == true && player[thisPlayer].grid[w][h] == isSHIP)
{cout << isWATER << " ";}
//If we have reached the border.. line feed
if (w == BOARD_WIDTH-1) cout << " ";
}
}
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.