0

I'm solving the 8 Queens Puzzle (place 8 queens on chessboard without conflicts) and created a class Square. Now I think this class should be the father of 2 subclasses Queen and Empty.

There is an other class: Chessboard that contains a bi-directional arrays, what I want is that when printing I will have 8 Q (Queens) and 56 E (empty see code).

These are the classes (I'll not write all):

class Square{
    int x;
    int y;
public :
Square() {};
Square(int ,int);
bool isAvaible();
void swapStatus();
virtual void printValue();
void setCoord(int,int);
int getX();
int getY();
};
void Square::printValue(){
    std::cout << "S ";
};

#include "square.hpp"

class Queen : public Square{
public:
    ...
    virtual void printValue();
    ...
};
void Queen::printValue(){
    std::cout << "Q ";
}

#include "Square.hpp"

class Empty : Square {
public:
    ...
    virtual void printValue();
    ...
};
void Empty::printValue(){
    std::cout << "E ";
}

At the beginning all elements inside Chessboard are Square, when a queen is added the Square must be replaced by the Queen. This is how I do it :

...
std::vector<std::vector<Square> > squares;
...

void Chessboard::setQueen(int x, int y){
    squares[x][y]=Queen(x,y);
}

I use this method to set 8 queen on the chessboard and when printing all squares this is the output :

S S S S S S S S 
S S S S S S S S 
S S S S S S S S 
S S S S S S S S 
S S S S S S S S 
S S S S S S S S 
S S S S S S S S 
S S S S S S S S 

Instead of :

Q S S S S S S S 
S Q S S S S S S 
S S Q S S S S S 
S S S Q S S S S 
S S S S Q S S S 
S S S S S Q S S 
S S S S S S Q S 
S S S S S S S Q 

Any suggestion?

Finley Adams
  • 773
  • 1
  • 8
  • 20

1 Answers1

3

Your squares vector (why a 2D vector? A fixed 2D array would make more sense) contains actual Square objects. As such, you can't store any Queen or Empty objects in it, as they would get sliced, which is what you are seeing happen.

You need to instead store Square* pointers in your squares vector.

For instance, you could create a separate array/vector of 8 Queen objects and 56 Empty objects, and then store Square* pointers to those objects in your squares, eg:

...
std::vector<std::vector<Square*> > squares; // or: Square* squares[8][8];
Queen queens[8];
int q_index = 0;
...

void Chessboard::setQueen(int x, int y){
    if (q_index < 8) {
        squares[x][y] = &queens[q_index++];
        squares[x][y]->setCoord(x, y);
    }
}

Or alternatively, just dynamically create all of your squares objects using new (preferably wrapped in std::unique_ptr), eg:

...
std::vector<std::vector<Square*> > squares; // or: Square* squares[8][8];
...

void Chessboard::setQueen(int x, int y){
    delete squares[x][y];
    squares[x][y] = new Queen(x, y);
}
...
std::vector<std::vector<std::unique_ptr<Square>>> squares; // or: std::unique_ptr<Square> squares[8][8];
...

void Chessboard::setQueen(int x, int y){
    squares[x][y] = std::make_unique<Queen>(x, y);
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Ok I didn't know about slicing, so the queen's function is lost because squares can contain only Square. I never used smart pointers but used some pointers in C (I'm new). If I understand what you're suggesting nothing has to change, just use pointers instead of objects and this is the trick right? – Finley Adams Oct 13 '21 at 21:22
  • Well, managing those pointers *correctly* can be tricky, in of itself. But yes, you need to use pointers (or references, but you can't have a vector of references) in order for virtual function calls to work. – Remy Lebeau Oct 13 '21 at 21:24
  • I'm sure it is...But this is the generic idea ok perfect thanks I will study these smart pointers. Do you now any website that explain it well? – Finley Adams Oct 13 '21 at 21:25
  • @FinleyAdams This is the best source of information: https://en.cppreference.com/w/cpp/memory/unique_ptr It may contain a lot of text - just read slowly, it explains everything you need. – alexpanter Oct 13 '21 at 21:31
  • @alexpanter You're very welcome! – Finley Adams Oct 14 '21 at 08:10