Skip to content

Austin637/Battleship-Game

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 

Repository files navigation

Battleship-Game

/*


** ** Battleship.cpp ** ** Author: Bary W Pollack ** ** A simple interactive "Battleship" game ** ** This program plays the game of "Battleship" on a 5 x 5 grid. ** The single battleship is randomly placed by the program, either ** horizontally or vertically in the grid. The player's job is to ** fire missiles at grid cells until the battleship has been sunk. ** ** The game could be extended quite easily to support a larger grid ** along with multiple warships. ** ** Also, one could consider creating various computer "strategies" ** for firing missles in a version of the game where a human places ** the ships and the computer attempts to sink them. ** ** Modified: 04/09/99 - created ** Modified: 04/10/99 - DisplayState changed to meet specs ** Modified: 04/11/99 - added captured output ** Modified: 10/18/10 - updated to VS 2008 **


*/

#include #include <time.h> // for seeding the random number generator

using namespace std;

// Random() and Randomize() have been "borrowed" from stdlib.h // since some C++ IDE's don't contain one or the other routine. // // Random(num) returns a random int in the range: 0 -(num-1) // Randomize seeds the pseudo-random number generator

#define Random(num)(int)(((long) rand() *(num))/(RAND_MAX+1))

void Randomize(void) { srand((unsigned) time(NULL)); }

/*


** Global constants and types


*/

// Bool, False, True used since some C++ compilers don't support 'bool' enum Bool { False = 0, True = 1 };

const int BRD_SIZE = 5; // size of the board const int SHIP_LTH = BRD_SIZE-1; // battleship length

enum CELL // contents of the board { //(for display purposes) EMPTY = '_', // empty cell - ocean HIT = 'X', // battleship hit by a missle MISS = 'O' // contains an exploded missle };

/*


** Class declarations for Battleship and BattleshipGame


** A Battleship is a ship that is positioned on the board in a ** fixed random position and orientation(horizontal or vertical). ** ** IsHit is the battleship's way to tell you if a missle fired to ** location(y,x) hits the ship. ** ** IsSunk is the battleship's way to tell you if it is sunk / afloat. ** ** Display is a routine used during development that allows you to ** see the(private) battleship data. **


*/

class Battleship { public: Battleship(void); Bool IsHit(const int y, const int x); Bool IsSunk(void); void Display(void);

private: struct ShipData { int y, x; Bool bHit; } shipData[SHIP_LTH]; };

/*


** A BattleshipGame is a game having a square board that contains ** a single(hidden) battleship. The game keeps track of the number ** of times you play, the number of missiles you fire, and the number ** of missiles that hit the battleship. ** ** Play currently plays a single game. Play is responsible for ** acquiring firing locations from the user, updating the board, ** and loops until the game is over. ** ** DisplayState is used by Play to display the current board state.


*/

class BattleshipGame { public: BattleshipGame(const int nGameNumber); void Play(void); void DisplayState(const char *sMsg);

private: CELL board[BRD_SIZE+1][BRD_SIZE+1]; Battleship ship; int nGameNumber; int nMissilesFired; int nHits; };

/*


** Implementation of class Battleship


** Constructor - randomly orients the battleship; randomly ** positions the battleship(but NOT on the board -- ** the battleship's position is HIDDEN from the game)


*/

Battleship::Battleship(void) { // offset into the board: flush against left or right side int nOffset = Random(2) + 1; // will be 1 or 2

// battleship will be either horizontal or vertical; not diagonal
if (Random(2))
{       // vertical battleship
int nI = Random(BRD_SIZE) + 1;
for (int j = 0; j < SHIP_LTH; j++)
{
    shipData[j].y = j + nOffset;
    shipData[j].x = nI;
    shipData[j].bHit = False;
}
}
else
{       // horizontal battleship
int nJ = Random(BRD_SIZE) + 1;
for (int i = 0; i < SHIP_LTH; i++)
{
    shipData[i].y = nJ;
    shipData[i].x = i + nOffset;
    shipData[i].bHit = False;
}
}

}

/*


** IsHit - returns True if a missile fired at(x,y) hits the ** battleship; otherwise it returns False. ** In case of a "hit," the hit is registered in the shipData.


*/

Bool Battleship::IsHit(const int y, const int x) { Bool bIsHit = False; for (int i = 0; i < SHIP_LTH; i++) if (shipData[i].y == y && shipData[i].x == x) { shipData[i].bHit = bIsHit = True; break; } return bIsHit; }

/*


** IsSunk -- returns True if the battleship is sunk(hit in all ** positions; it returns False otherwise


*/

Bool Battleship::IsSunk(void) { Bool bIsSunk = True; for (int i = 0; i < SHIP_LTH; i++) if (! shipData[i].bHit) { bIsSunk = False; break; } return bIsSunk; }

/*


** This debug routine was used during development so that we could ** see where the battleship actually is located and can track the ** shipData as the game is played.


*/

void Battleship::Display(void) { cout << "Battleship: "; for (int i = 0; i < SHIP_LTH; i++) cout << "(" << shipData[i].y << " " << shipData[i].x << (shipData[i].bHit ? " *)" : " .)"); cout << endl; }

/*


** Implementation of class BattleshipGame


** The constructor sets up the game. This includes initialization ** of the entire board as well as other game-related data such as ** the game number, number of missiles fired and hits.


*/

BattleshipGame::BattleshipGame(const int nGameNumber) { this->nGameNumber = nGameNumber;

for (int j = 1; j <= BRD_SIZE; j++)
for (int i = 1; i <= BRD_SIZE; i++)
    board[j][i] = EMPTY;

nMissilesFired = nHits = 0;

}

/*


** Play implements one "game:" repeatedly asking for pairs of ** missile coordinates, updating the board, tracking the number of ** fired missiles and the number of hits, redisplaying the board, ** until the battleship is sunk. ** ** Some simple range-checking is done on the values of y and x. ** ** Note: a y or an x coordinate <= zero aborts the current game. ** ** Coordinate convention:(y x), with y increasing downwards and ** x increasing to the right ** ** x --> ** ** 1 2 3 4 5 ** 1 . . . . . ** 2 . . . . . ** y 3 . O O X . ** | 4 . . . X . ** V 5 . . . . . ** ** Note: the 0-row and 0-column of the board(array) are "ignored" ** so that we can use "natural" values for indices. **


*/

void BattleshipGame::Play(void) { while (! ship.IsSunk()) { int y, x;

DisplayState("The current situation:");

// There is a reasonable argument to make the acquisition of the
// user's input process into a separate routine. And, in general,
// you probably should. But, in this program there's so little to
// do that there isn't much of an advantage to do so. So I didn't.

cout << "Fire missile to coordinates (y x): ";
x = y = -1;
cin >> y;
if (y <= 0)     // abort?
    break;
cin >> x;
if (x <= 0)     // abort?
    break;

if (x > BRD_SIZE || y > BRD_SIZE)
{
    cout << "Each coordinate must be in the range 1-" << BRD_SIZE << endl
	 << "Please try again..." << endl << endl;
    continue;
}
if (board[y][x] != EMPTY)
    cout << "That's foolish!  You've already fired at("
	 << y << "," << x << ")" << endl;

// now, enter the user's data and record the results

++nMissilesFired;
if (ship.IsHit(y, x))
{
    board[y][x] = HIT;
    ++nHits;
}
else
    board[y][x] = MISS;

// protection against infinite loops in IDEs like Borland...
// if (nMissilesFired > BRD_SIZE*BRD_SIZE)  break;  //FOO
}

if (ship.IsSunk())
DisplayState("Down she goes!");

}

/*


** Display the state of the game: board, missiles fired, hits...


*/

void BattleshipGame::DisplayState(const char *sMsg) { int j, i;

cout << endl << endl << sMsg << endl << endl << ' ';

for (i = 1; i <= BRD_SIZE; i++)
cout << ' ' << i;
cout << endl;

for (j = 1; j <= BRD_SIZE; j++)
{
cout << j << ' ' << char(board[j][1]);
for (i = 2; i <= BRD_SIZE; i++)
    cout << '|' << char(board[j][i]);
cout << endl;
}

// ship.Display();             //FOO - for development only...
cout << endl
 << "Game: " << nGameNumber << "   "
 << "Missle Count: " << nMissilesFired << "   "
 << "Hits: " << nHits
 << endl << endl;

}

/*


** The main routine plays multiple games of Battleship.


*/

int main(void) { Randomize();

cout << endl << "* * B A T T L E S H I P * *" << endl;

char ch;
int  nGameNumber = 0;
do              // play one game
{
int nLoopCount = 3;	// deal with bad input
BattleshipGame game(++nGameNumber);
game.Play();
do          // ask user about playing again;
{           // again, this could be a separate routine...
    cout << "Game Over!" << endl << endl
	 << "Would you like to play again (y/n)? ";
    cin >> ch;
    ch = (char) tolower(ch);
    if (--nLoopCount < 0)
	break;
} while (ch != 'y' && ch != 'n');

} while (ch == 'y' && nGameNumber < 20);	// deal with bad input

cout << endl << "Thanks for playing..." << endl << endl;

return 0;

}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors