Straightfw
Straightfw

Reputation: 2211

Weird behaviour of a class after adding one method

So I'm working on simple console battleships in C++. I have a class Ship like this:

class Ship {
    public:
        virtual void draw(int x, int y){}
        virtual void shoot(int x, int y){}
        virtual bool isDead(){};
};

and two classes (horizontal and vertical ship) which inherit from it. So a sample vertical one is:

class VertShip : public Ship{
    private:
        int x, y, shipSize;
        char deck[4];
    public:
        VertShip(int x, int y, int shipSize) : x(x), y(y), shipSize(shipSize) {
            for(int i=0; i<shipSize; ++i)
            {
                deck[i] = '_';
            }
        }
        virtual void draw(int x, int y){
            cout << deck[y - this->y];
        }
        virtual void shoot(int x, int y){
            deck[y - this->y] = 'T';
            --shipSize;
        }

        virtual bool isDead()
        {
            if(this->shipSize) return 0;
            return 1;
        }
};

so just each of the cells of my deck is represented inside the object. Shoot() runs when someone invokes the fire() method on the Board class and successfully hits the ship and draw() gives the drawBoard() method information about a given cell of the ship's deck. Also, ships[] is an array of pointers to the ships objects. So up to this point everything works fine - the problem is with the Board::fire():

void Board::fire(int w, int k){
    if(mapOfCells[w][k]>=0)
        ships[mapOfCells[w][k]]->shoot(w,k);
        //if(ships[mapOfCells[w][k]]->isDead()) cout<<"The ship has drown.\n";
    else
        mapOfCells[w][k]=-2;
}

As soon as I uncomment the if, the weird behaviour starts. It gives me improper information (claiming that cells with ship in them are empty and the other way around too) and the game crashes after three shots. If I comment it, however, it works perfectly - just doesn't let you know if you sunk a ship completely.

What's wrong with it? Am I doing something malicious in this one if? Regretfully, I'm unable to provide a short, compilable source as this game simply won't run without most of the classes and methods and there's quite a few of them.

Upvotes: 0

Views: 82

Answers (2)

Adam H. Peterson
Adam H. Peterson

Reputation: 4601

Try putting curly braces around your if clause. Your else clause is binding to the second if statement rather than the first, and your second if statement is being executed unconditionally.

Upvotes: 4

Devolus
Devolus

Reputation: 22094

If you simply uncomment this then the semantics changes:

Currently it is:

void Board::fire(int w, int k)
{
    if(mapOfCells[w][k]>=0)
        ships[mapOfCells[w][k]]->traf(w,k);
    else
        mapOfCells[w][k]=-2;
}

if you uncomment, it becomes:

void Board::fire(int w, int k)
{
    if(mapOfCells[w][k]>=0)
        ships[mapOfCells[w][k]]->traf(w,k);

    if(ships[mapOfCells[w][k]]->isDead())
        cout<<"The ship has drown.\n";
    else
        mapOfCells[w][k]=-2;
}

not sure if this is intended. Your unexpected behaviour could come from this though, because your indentation looks like you intended something else. As noted above, your default implementation also lacks a return value which should give you a compiler warning and undefined results.

Upvotes: 5

Related Questions