Loading...
kaminka avatar kaminka 5 Точки

Task3. Chess Figures - Full OOP C++ Homework

Здравейте, 

За тази задача си имам освен клас за всяка фигура и един общ клас "Figure", който после всяка фигура го наследява: 

class Figure {
public:
    char symbol; // * Pawn // % Knight // & Bishop // # Rook // $ Queen // ! King
    bool color; // true->white false->black
    std::string position; //ex. G3

    virtual std::string* getAvailableMoves(const Figure & otherFigures) = 0;
    virtual bool moveFigure(const std::string newPosition, Figure & otherFigures) = 0;
};

Сигурно вече сте забелязали и къде ми е проблема. Имам затруднение с параметъра на функциите getAvailableMoves(otherFigures) и move(newPosition, otherFigures). Разбирам, че трябва да е array от пойнтъри като в демото от лекцията. Ама нещо нито мога да го сложа като параметър, нито после в main() да извикам функцията. Ето го main():

int main()
{
    typedef Figure * FigurePtr;
    FigurePtr figuresArr[32]{
        new Pawn(true,"A2"),
        new Pawn(true,"B2"),
        new Pawn(true,"C2"),
        new Pawn(true,"D2"),
        new Pawn(true,"E2"),
        new Pawn(true,"H2"),
        new Pawn(false,"A7"),
        new Pawn(false,"B7"),
        new Pawn(false,"C7"),
        new Pawn(false,"D7"),
        new Pawn(false,"E7"),
        new Pawn(false,"F7"),
        new Pawn(false,"G7"),
        new Pawn(false,"H7")
    };

    Pawn p1(false,"G7");

    bool test = p1.moveFigure("G6",figuresArr);

    std::cout << test;

    return 0;
}

Може ли някой да ми помогне с този параметър? Какъв трябва да бъде и как се вика?

Тагове:
1
C++ Programming 19/04/2017 16:30:52
georgi.stef.georgiev avatar georgi.stef.georgiev 921 Точки
Best Answer

Здравей,

Ако искаш да е array от pointer-и към обекти от Figure, не трябва да ползваш const Figure &, а ти трябва const Figure **. Както Мартин е казал, не е задължително да е array от pointers - затова нарочно е оставено без тип данни, за да може да го направите както искате, без да ви ограничавам с някакъв конкретен интерфейс.

Но да, array от pointers би бил добра идея. В твоя код ти просто подаваш референция (не pointer) към една фигура. Референциите като цяло са винаги към едно нещо, не към масив от неща (и не можеш да направиш масив от референции, това C++ не го позволява - най-вече защото няма default ctor за референция, но нека не задълбаваме в това).

От лекцията за масиви знаем, че можем да си направим int масив (от 10 елемента) така:

int * arr = new int[10];

А ако искаме да си направим масив от някакъв си тип данни, наречен - да речем - T, тогава:

Т * arr = new Т[10];

Ти това, което искаш, е масив, който ти дава достъп до другите фигури. Понеже другите фигури наследяват Figure, за да имаш масив от тях, трябва да имаш масив от pointers към тях, за да можеш да ползваш свойствата на полиморфизма (това го знаем от Full C++ OOP лекцията - това явно и ти си се сетила, щом си решила да ползваш масив от pointers.

Тоест типа на обектите в твоя масив е Figure* - указател към Figure. И по-конкретно const Figure*, защото няма да променяш подадените фигури, само ще ги четеш. Тоест:

const Figure ** figures
или с typedef, както ти си направила:
typedef Figure * FigurePtr; //или typedef const Figure * FigurePtrConst;
FigurePtr * figures = new Figure[32] { new Pawn(...), ... }

(в този пример figures е инициализирано в динамичната памет, в твоя main e в auto паметта - това няма значение за текущия проблем).

Тоест вярно си инициализирала и декларирала масива, но виж параметъра, който ползваш за метода: 

virtual bool moveFigure(const std::string newPosition, Figure & otherFigures) = 0;

Параметърът ти е референция към една фигура, не pointer към масив от FigurePtr. Тоест:

virtual bool moveFigure(const std::string newPosition, FigurePtr * otherFigures) = 0;

Разбира се тук typedef-а ти трябва да е видим за класа, тоест най-вероятно трябва да го напишеш преди класа. И също, понеже имаш pointer, не е лошо да подадеш и размера на този масив, към който сочиш, защото иначе няма как да знаеш колко елементи има в това otherFigures (другия вариант е да ползваш vector<FigurePtr> otherFigures, така otherFigures ще можеш да му кажеш .size(), или пък да си направиш FigurePtrSmartArray):

typedef Figure * FigurePtr;
class Figure {
...
    virtual std::string* getAvailableMoves(FigurePtr * otherFigures, int numOtherFigures) = 0;
    virtual bool moveFigure(const std::string newPosition, FigurePtr * otherFigures, int numOtherFigures) = 0;
};

Оттам нататък кодът, с който го викаш, е верен и в момента, само трябва да добавиш 32 като параметър за бройката фигури, които са ти в масива.

Поздрави,

Жоро

 

P.S.:

// $ Queen

$... :D :D :D

0
19/04/2017 23:51:02
kaminka avatar kaminka 5 Точки

Много благодаря за изчерпателните отговори всеки път! Много ми помагат. 

Ще си го оправя както казваш, защото ми е много интересно да използвам array от пойнтъри, които сочат към различни обекти(фигури), както с овцата и паяка. 

А това с долара за кралицата е станало съвсем случайно :D :D. 

0
MartinBG avatar MartinBG 4803 Точки

В условието на задачата не е указан типа на този параметър, а само информацията, която трябва да носи:

getAvailableMoves(otherFigures) – gets a parameter which represents all other figures on the board (but doesn’t allow changing those other figures in any way – ensure that through the type of the parameter) and returns an array of positions to which this figure can make a valid move, based on its current position AND the positions of the other figures

Аз лично реших да използвам char array, който представлява цялата игрална дъска с всички фигури на нея:

typedef std::array<char, BOARD_SIZE> ChessBoard;

class ChessFigures
{
public:

    virtual std::vector<std::string> getAvailableMoves(const ChessBoard & otherFigures) const = 0;

    bool move(const std::string & newPosition, const ChessBoard & otherFigures)
    { ... }

...

}

Разбира се, това е само едно от многото възможни решения.

Мога да споделя и цялото решение на домашното си, ако те интересува.

0
kaminka avatar kaminka 5 Точки

Здравей Мартин, 

Благодаря ти за отговора. 

Би ми било интересно да видя твоето решение, тъй като е разлчино от моето и ми е интересно да видя друг подход за имплементацията на тази задача. 

0
MartinBG avatar MartinBG 4803 Точки

Заповядай:

4-chess-figures.h

4-chess-figures.cpp

5-chess-game.h

5-chess-game.cpp

Пиши, ако имаш някакви въпроси по решенията ми, и ще се опитам да ги разясня.

Сега, като ги погледнах, виждам, че има какво да се желае по тях като OOP организация, но докато ги писах, това ми беше един от малките проблеми :)

Поздрави!

0
20/04/2017 20:40:53
kaminka avatar kaminka 5 Точки

Окей, мерси. 

0
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.