1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <limits>
#include <vector>
// coordinates (location) of the ship and shots
struct location {
int x; // 1 through FIELD_SIZE
int y; // 'a' through FIELD_SIZE
location(int x_arg = -1, int y_arg = -1) : x { x_arg }, y { y_arg } {}
};
// contains ship's coordinates (location) and whether is was sunk
struct ship {
location loc;
bool sunk;
};
struct Board {
std::vector<std::vector<int>> board;
int sinked { '#' },
guess { 'S' };
explicit Board(int val);
friend std::ostream& operator<<(std::ostream& os, const Board& myb)
{
os << " 0 1 2 3 4 5 6 7 8 9\n";
int seq {};
for(const auto& a : myb.board) {
os << seq++;
for(const auto i : a) { os << ' ' << static_cast<char>(i); }
os << '\n';
}
return os;
}
};
Board::Board(int val)
{
board.resize(val, std::vector<int>(val, ' '));
}
// initialization functions
void initialise(ship[], const int);
location pick(const int);
bool match(const ship&, const location&);
int check(const ship[], const int, const location&);
void deploy(ship[], const int, const int);
// display functions
void printShip(ship);
void printFleet(const ship[], const int);
// battle functions
bool operational(const ship[], const int);
location fire(int);
void sink(ship&);
void waitForEnter();
int main()
{
std::srand(((unsigned)time(0)));
constexpr int FLEET_SIZE = 5; // number of battleships
constexpr int FIELD_SIZE = 10; // the field (ocean) is FIELD_SIZE x FIELD_SIZE
ship s[FLEET_SIZE]; // enemy ship structure with 5 elements
initialise(s, FLEET_SIZE);
deploy(s, FLEET_SIZE, FIELD_SIZE);
ship user; // users fire guess
Board myb(FIELD_SIZE);
std::cout << "WELCOME TO BATTLESHIP\n"
"_____________________\n\n"
" -Sink enemy ships-\n\n\n"
"You have the option to view the status of the ships or go "
"straight to the game.\n\n";
// run this while there is at least one standing ship
while(operational(s, FLEET_SIZE)) {
user.loc = fire(FIELD_SIZE);
int c = check(s, FLEET_SIZE, user.loc);
if (c != -1) {
sink(s[c]);
std::cout << "HIT! Ship sunk.\n\n";
myb.board.at(user.loc.y).at(user.loc.x) = myb.sinked;
} else {
std::cout << "Sorry you missed, try again.\n\n";
myb.board.at(user.loc.y).at(user.loc.x) = myb.guess;
}
std::cout << myb << '\n';
}
std::cout << "\nCongratulations! You have sunk all enemy ships.\n\n";
waitForEnter();
}
// places all ships in -1 X location to signify that the ship is not deployed
void initialise(ship s[], const int size)
{
for(int i=0; i<size; i++) { s[i].loc.x = -1; }
}
// places an array of battleships in random locations in the ocean
void deploy(ship s[], const int fsize, const int osize)
{
for(int i = 0; i<fsize; ++i) {
location temp = pick(osize);
int e = check(s, fsize, temp);
if (e == -1) {
s[i].loc = temp;
s[i].sunk = false;
}
}
}
// generates a random location
location pick(int size) { return { rand() % size, rand() % size }; }
// returns the index of the element of the ship[] array that matches location.
// Returns -1 if none match
int check(const ship s[], const int size, const location& loc)
{
// if true, return the index, if not return -1
for(int i=0; i < size; ++i) {
if (match(s[i], loc)) { return i; }
}
return -1;
}
// returns true if this location matches the location of the ship
// returns false otherwise
bool match(const ship& s, const location& l)
{
// if both member variables match, return true
if ((s.loc.x == l.x) && (s.loc.y == l.y)) { return true; }
else { return false; }
}
// returns true if at least one ship in the array is not sunk
bool operational(const ship s[], const int size)
{
for(int i = 0; i < size; ++i) {
if (s[i].sunk == false) { return true; }
}
return false;
}
// prints the location and status (sunk or not) of a single ship
void printShip(ship s)
{
std::cout << s.loc.y << s.loc.x << ' ';
if(s.sunk == true) { std::cout << "sunk "; }
else if (s.sunk == false) { std::cout << "up "; }
}
// prints the locations of all the ships and whether they are sunk
void printFleet(const ship s[], const int size)
{
for(int i = 0; i < size; ++i) {
printShip(s[i]);
}
std::cout << '\n';
}
// asks the user to input the coordinates of the next shot
location fire(int max)
{
location temp;
do {
std::cout << "\nWhere would you like to fire a shot?\n"
"Y-Coordinate <0-9>: ";
std::cin >> temp.y;
std::cout << "X-Coordinate <0-9>: ";
std::cin >> temp.x;
std::cout << '\n';
} while( temp.x < 0 || max <= temp.x
|| temp.y < 0 || max <= temp.y );
return temp;
}
// sinks the ship
void sink(ship& s) { s.sunk = true; }
void waitForEnter()
{
std::cout << "\nPress ENTER to continue...\n";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
|