Use constructors.
struct Location {
int x; // 1 through fieldSize
char y; // 'a' through fieldSize
// constructor
Location(): x(-1), y(`*`)
{
)
};
Now every time you make a location it will always come out with x == -1
and y == '*'
with no further effort. With
struct Ship {
Location loc;
bool sunk;
Ship(): sunk(false)
{
}
};
every Ship
comes out of the factory unsunk and at -1, '*'.
So
Ship myFleet[fleetSize];
Just made and initialized fleetSize
unsunk Ship
s at -1, '*' with no further effort on your part.
As for passing the array, when you call a function with an array, the size of the array is lost. Read What is array decaying? for more on that.
So
void initialize(Ship[]);
could be
void initialize(Ship ships[fleetsize]);
if fleetsize is a compile-time constant, a value set in the code and can never be changed so that the compiler can generate array indexes, and know the size allowing some optimizations.
Or
void initialize(Ship * ships, size_t fleetsize);
if fleetsize
is not a fixed value and can change at runtime. A dynamic fleetsize
can result in the program having to manage dynamic memory, and this can be trickier than it looks.
But...
C++ offers a number of "Containers" that can be used instead of arrays. These containers know their size, manage dynamic memory for you, and generally make life easier with an array of sifting, searching, and sorting tools either built right in or in the <algorithm>
library. The two that look particularly useful to your usecase are std::vector
, a dynamic array and std::array
, a statically-sized array.
Edit: Random Locations
RNG set up code gleefully stolen from: std::uniform_int_distribution
#include <random>
std::random_device rd; // cannot be trusted with mingw. Use time(null) instead
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(1, 5);
struct Location {
int x; // 1 through fieldSize
char y; // 'a' through fieldSize
// constructor. Note
Location()
{
do
{
x = dis(gen); // number
y = 'a'+dis(gen)-1; // requires sequentially ordered character set like ASCII
} while(locIsOccupied(x,y)); // ensure x and y are unused.
)
};
I've left locIsOccupied
unimplemented.
Another stupid trick is
A vector<Location> locations
containing all possible Locations
. random_shuffle
locations
and
struct Ship {
Location loc;
bool sunk;
// construct Ship with location from available pool
// using locations.back() because it's cheapest to remove the last item
Ship(): loc(locations.back()), sunk(false)
{
locations.pop_back(); // remove location so it can't be chosen again
}
};