-2

I have these two structures:

const int fleetSize = 5; 
const int fieldSize = 5;

struct Location {
    int x;  // 1 through fieldSize
    char y; // 'a' through fieldSize
};

struct Ship {
    Location loc;
    bool sunk;
};

I also have this prototype in a header file:

void initialize(Ship[]);

In main, I call a function from a separate source file that is supposed to assign -1 to all the 'x' values of location and a '*' to all the 'y' values as denoted here:

int main()
{
    Ship myFleet[fleetSize];
    initialize(myFleet);
}

My problem is I have no idea where to go from here. All I have is this:

void initialize (int a[])
{
    for (int i = 0; i < fleetSize; i++)
    {
        a[i] = -1;
    }
}

I have no idea what this is even doing, if anything, because I can't debug due to lots of LNK errors I cannot figure out either. So my question is, is this right? And if yes, how do I go about assigning an asterisk to each 'y'?

So, each element of x needs to be -1 and each element of y needs to be *.

Inert
  • 1
  • 6
  • 6
    Use `std::vector` or `std::array`; they are easier to pass than an array. – Thomas Matthews Nov 06 '16 at 18:14
  • I'm sorry, I should have noted this is a project for school. I'm sadly required to use structures :(. – Inert Nov 06 '16 at 18:16
  • 2
    So use the structures. `vector` doesn't stop that. `std::vector myFleet;` Also read up on constructors. They will make your job much much easier even with an array. – user4581301 Nov 06 '16 at 18:17

3 Answers3

1

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 Ships 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
    }
};
Community
  • 1
  • 1
user4581301
  • 33,082
  • 7
  • 33
  • 54
  • Thank you for the advice. I guess the problem with not posting all of my code online or asking for help online in general is the lack of context. I actually have to set the location to -1 and * but then randomly generate a location for the 5 ships in a 5x5 grid of 1-5 and a-e. Similar to an actual game of battleship. Regardless, thank you for taking the time out of your day to help me. – Inert Nov 06 '16 at 18:57
  • Not a problem. There is no reason you can't do the random positioning inside the constructor as well. You would just have to make sure you don't place two ships in the same place. – user4581301 Nov 06 '16 at 19:14
  • @ChristianVokurka added a couple simple ideas on how to randomize the locations – user4581301 Nov 06 '16 at 19:35
0
a[i].loc.x = -1;
a[i].loc.y = '*';
Edward Strange
  • 40,307
  • 7
  • 73
  • 125
  • I'm getting an error that my expression must have a class type? What does that all mean? Is it not an array denoted by the parameter of the function? – Inert Nov 06 '16 at 18:20
  • Oh, I missed that you expect an array of ints. That won't ever work. You need to accept array of Ship. And no, it's not actually an array but a pointer. However, arrays and pointers accept the same syntax. `a[i]` is the same as `*(a + i)`. – Edward Strange Nov 06 '16 at 18:35
  • 1
    Also, user48something's answer is better and the right way to do it in C++. But if you're answering a homework problem you may be stuck doing it this way. Just keep in mind that it's not idiomatic C++. – Edward Strange Nov 06 '16 at 18:37
  • Thanks for the feedback. I actually didn't know that a[I] stood for that. I always love learning new things, even if I can't always figure out how to use them correctly! :P – Inert Nov 06 '16 at 18:58
0
void initialize(Ship[]);

stands for a function called initialize which takes an array of Ships of unknown size and returns nothing.

You can't iterate over the array unless you know its size:

void initialize(Ship[] array, std::size_t size)
{
    for (std::size_t i = 0; i < size; ++i)
    {
        array[i].loc.x = -1;
        array[i].loc.y = '*';
    }
}
  • Yeah, I see what you're saying. All of this code was provided to me by my instructor who specifically told us not to modify his code, only add our own to make it work. I'm still new to all this but I would be willing to bet there is a connection of size here. In main, there is this; Ship myFleet[fleetSize]; - which is really ship myfleet [5] as fleetsize is a constant. He then wrote initialize(myFleet); which leads me to believe somewhere else is where the size is supposed to be declared as it is not passed to the function. At least I think... – Inert Nov 06 '16 at 19:02
  • Is that constant global? If yes, the function would have access to it. – Alexander Aleksandrovič Klimov Nov 06 '16 at 19:19