[ llux @ 16.11.2011. 20:52 ] @
Imam klasu chessPiece. Za svaku figuru funkcije i clanovi su isti, osim sto za neke postoje i dodatne kao npr promote();
U programu koji ce koristiti tu klasu moram da napravim vector of chessPieces. Ako bih koristio nasledjivanje, morao bih da napravim nekoliko vektora za svaku figuru, sto dodatno komplikuje program.
E sad je pitanje, da li da koristim ono sto je logicno (inheritance) ili ono sto je lakse?
Verovatno i implementacija klase nije bas najbolja ali to trenutno nije ni bitno.
Malo je nezgodno kad se izvrsava u komandnom prozoru, jer su komande za pomeranje figura nesto kao Pa2 a3.
I onda se mora napraviti funkcija za konvertovanje ili povezivanje sa brojevima. Pa se to sve mora povezati sa klasom. Napominjem da nikada nisam video nijedan primer saha, jednostavno zelim sam nesto da napravim pa cu posle da pregledam neke primere.
[ glorius @ 17.11.2011. 13:32 ] @
Ja sam za verziju sa nasledjivanjem. Imaces vise klasa ali je kod zato cistiji i laksi za odrzavanje. Kada ne bi isao preko nasledjivanja move() funkcija bi bila ogromna (ok, uvek se moze refaktorisati i rasclaniti na manje funkcije ali je po meni bolja ideja da uradis preko nasledjivanja). Sto se tice vektora, nisam razumeo u cemu ti je problem tako da cu ti napisati i klasu PieceManager koja enkapsulira rad sa figurama koje se drze u jednom vektoru (jedan vektor za bele, jedan za crne).

Code:


enum PieceType { PT_Pawn, PT_King, PT_Queen, ... };

struct POSITION
{
     char x;
     int y
};

class ChessPiece
{
public:
      ChessPiece(POSITION startPos, ...);

      virtual bool move(POSITION target);
      virtual void promote() { ASSERT(false) }; // samo ce neke od izvedenih klasa imati funkciju promote tako da ako slucajno pozoves promote() za izvedenu klasu koja nema override-ovanu metodu promote() aplikacija ce signalizirati sa assert
      PieceType type() const { return m_type; }
priotected:
      POSITION m_pos;
      PieceType m_type; // mozes koristiti promenljivu ili RTTI za proveru tipa figurice
};

class Pawn : public ChessPiece
{
public:
     Pawn(POSITION startPos) : ChessPiece(startPos)
                                         , m_type(PT_Pawn)
                                         {...}

     virtual bool move(POSITION target);
     virtual void promote() { ... }
};

....

enum Player { Black, White};

class PiecesManager
{
public:
     static PiecesManager& instance() { ... }

     // funkcije za manipulaciju figurama
     int numberOfPawns(Player player);
     ....
     void removePiece(Player player, ChessPiece* piece); // figurica je "pojedena"
     ChessPiece* pieceAtPosition(POSITION pos) const;
private:
     std::vector<ChessPiece*> m_whitePieces;
     std::vector<ChessPiece*> m_blackPieces;
};


[ llux @ 17.11.2011. 16:28 ] @
U ovom trenutku necu gledati nijedan kod.
Zapravo, funkcija move je kod mene vrlo jednostavna. I ista je za svaku figuru.
Hteo sam da kazem da ako napravim samo jednu klasu, sve figure mogu da smestim u jedan vektor i kod ce biti manje komplikovan. A ako napravi razlicite figure, samo cu pesake moci da smestim u jedan vector. Za ostale figure nesto drugo.
Pitanje je da kada sam u ovakvoj nedoumici, da li da izaberem jednostavniji i laksi metod ili da radim logicki iako mi se eventualno zakomplikuje kod?
[ glorius @ 17.11.2011. 16:47 ] @
Odluka je na tebi. Polimorfizam ( koji ja koristim u datom primeru ) je, moze se reci, zamena za switch izraze. Tako da ces umesto reimplementacije funkcije move() u izvedenim klasama imati switch iskaz u jedinstvenoj move funkciji koji proverava koji je tip figure i u zavisnosti od toga pomerati figuru ako budes koristio samo jednu klasu za sve tipove figurica. Isto je i za promotion.
Za pocetak mozes napraviti prototip, to je draft prikaz aplikacije. Ideja je da ispitas koje ces sve objekte imati u aplikaciji, njihovu medjusobnu interakciju (bez mnogo ulazenja u detalje sto se tice podataka klasa) i ako ti se svidi dizajn prototipa mozes da nastavis sa takvim dizajnom.
Na kraju, slobodan si da uradis kako ti zelis, vazno je da 'kuckas' jer se tako najbolje stice iskustvo i vremenom ces lakse moci da predvidis kakav dizajn najvise odgovara tipu aplikacije koju pravis.
[ llux @ 17.11.2011. 16:58 ] @
Funkcija move mi je ista za svaku figuru. Ne treba reimplementacija.
Vrlo je jednostavna, cuva trenutnu poziciju figure, pa joj se proslede argumenti za novu poziciju. Sve potrebne provere radi programer koji koristi klasu. Kazem, mozda je losa implementacija klase ali to je nebitno skroz.
[ glorius @ 17.11.2011. 17:16 ] @
Ok, ja sam dao primer sa nasledjivanjem posto je takav naslov teme :)

Svakako da bi za pocetak trebao da uradis onako kako ti je lakse (ne znam koliko imas iskustva sa C++ i programiranjem).
Za pocetak uradi kako ti odgovara pa bi mogao i da postavis aplikaciju da vidimo kako napreduje :).
[ Nedeljko @ 17.11.2011. 18:34 ] @
Poenta nasleđivanja je da možeš sve figure da smestiš u jedan vektor. Dakle iz apstraktne klase Piece izvedene su klase Pawn, Rook, Knight, Bishop, Queen i King. U vektor tima vector<Piece*> možeš smeštati pokazivače na sve tipove figura.
[ llux @ 17.11.2011. 22:34 ] @
Shvatio sam da mi funkcija move ne moze nikako biti ista za sve figure. Definitivno cu koristiti inheritance. Kako je lako prevideti neke stvari.
[ llux @ 18.11.2011. 18:33 ] @
@glorius

Moje iskustvo je pocetnicko.

U ovom trenutku mogu da ti postavim samo kod koji mi sluzi za testiranje svih mojih zamisli.

Koristim jednog pesaka i sve drzim u jednom fajlu. Nisu uradjene nikakve provere kao npr dali je potez legalan i slicne.

Kad istestiram tek se onda bacam na pravu implementaciju i bolje uredjenje koda:




Code:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
using namespace std;


int convertChar(char c)
  {

switch (c)
{
case '1':
case 'a': return 0;

case '2':
case 'b': return 1;

case '3':
case 'c': return 2;

case '4':
case 'd': return 3;

case '5':
case 'e': return 4;

case '6':
case 'f': return 5;

case '7':
case 'g': return 6;

case '8':
case 'h': return 7;
default: return -1;
}
  }





class pawn {

int Mposx, Mposy;
char Mcolor;
string Mposition;
bool Meated;


public:

pawn(string position, char color)

{Mposy=convertChar(position[0]);
 Mposx=convertChar(position[1]);

 Mcolor=color; Mposition=position; Meated=false;
 }

void setOnBoard(string board[8][8]){board[Mposx][Mposy]=(Mcolor=='b')?"Pb":"Pw";}

string getStrPosition(){return Mposition;}



 void move(string toPosition, string board[8][8])
 {

     if ((Mposx+Mposy)%2) board[Mposx][Mposy]="  ";
else board[Mposx][Mposy]="//";

     Mposy=convertChar(toPosition[0]);
     Mposx=convertChar(toPosition[1]);

     Mposition=toPosition;

board[Mposx][Mposy]=(Mcolor=='b')?"Pb":"Pw";

 }



        };




    int whatPiece(string position, vector<pawn> pwn)
{
    for (int i=0; i<pwn.size(); i++)
                        if (pwn[i].getStrPosition()==position) return i;

    return -1;
}







    void displayBoard (string board[8][8])
    {
        cout<<"\n"
"     A      B      C      D      E      F      G      H    \n"
"  ---------------------------------------------------------\n"
"  |      |//////|      |//////|      |//////|      |//////|\n"
"  |      |//  //|      |//  //|      |//  //|      |//////|\n"
" 8|  "<<board[7][0]<<"  |- "<<board[7][1]<<" -|  "<<board[7][2]<<"  |- "<<board[7][3]<<" -|  "<<board[7][4]<<"  |- "<<board[7][5]<<" -|  "<<board[7][6]<<"  |- "<<board[7][7]<<" -|\n"
"  |      |//  //|      |//  //|      |//  //|      |//  //|\n"
"  |      |//////|      |//////|      |//////|      |//////|\n"
"  ---------------------------------------------------------\n"
"  |//////|      |//////|      |//////|      |//////|      |\n"
"  |//  //|      |//  //|      |//  //|      |//  //|      |\n"
" 7|- "<<board[6][0]<<" -|  "<<board[6][1]<<"  |- "<<board[6][2]<<" -|  "<<board[6][3]<<"  |- "<<board[6][4]<<" -|  "<<board[6][5]<<"  |- "<<board[6][6]<<" -|  "<<board[6][7]<<"  |\n"
"  |//  //|      |//  //|      |//  //|      |//  //|      |\n"
"  |//////|      |//////|      |//////|      |//////|      |\n"
"  ---------------------------------------------------------\n"
"  |      |//////|      |//////|      |//////|      |//////|\n"
"  |      |//  //|      |//  //|      |//  //|      |//  //|\n"
" 6|  "<<board[5][0]<<"  |- "<<board[5][1]<<" -|  "<<board[5][2]<<"  |- "<<board[5][3]<<" -|  "<<board[5][4]<<"  |- "<<board[5][5]<<" -|  "<<board[5][6]<<"  |- "<<board[5][7]<<" -|\n"
"  |      |//  //|      |//  //|      |//  //|      |//  //|\n"
"  |      |//////|      |//////|      |//////|      |//////|\n"
"  ---------------------------------------------------------\n"
"  |//////|      |//////|      |//////|      |//////|      |\n"
"  |//  //|      |//  //|      |//  //|      |//  //|      |\n"
" 5|- "<<board[4][0]<<" -|  "<<board[4][1]<<"  |- "<<board[4][2]<<" -|  "<<board[4][3]<<"  |- "<<board[4][4]<<" -|  "<<board[4][5]<<"  |- "<<board[4][6]<<" -|  "<<board[4][7]<<"  |\n"
"  |//  //|      |//  //|      |//  //|      |//  //|      |\n"
"  |//////|      |//////|      |//////|      |//////|      |\n"
"  ---------------------------------------------------------\n"
"  |      |//////|      |//////|      |//////|      |//////|\n"
"  |      |//  //|      |//  //|      |//  //|      |//  //|\n"
" 4|  "<<board[3][0]<<"  |- "<<board[3][1]<<" -|  "<<board[3][2]<<"  |- "<<board[3][3]<<" -|  "<<board[3][4]<<"  |- "<<board[3][5]<<" -|  "<<board[3][6]<<"  |- "<<board[3][7]<<" -|\n"
"  |      |//  //|      |//  //|      |//  //|      |//  //|\n"
"  |      |//////|      |//////|      |//////|      |//////|\n"
"  ---------------------------------------------------------\n"
"  |//////|      |//////|      |//////|      |//////|      |\n"
"  |//  //|      |//  //|      |//  //|      |//  //|      |\n"
" 3|- "<<board[2][0]<<" -|  "<<board[2][1]<<"  |- "<<board[2][2]<<" -|  "<<board[2][3]<<"  |- "<<board[2][4]<<" -|  "<<board[2][5]<<"  |- "<<board[2][6]<<" -|  "<<board[2][7]<<"  |\n"
"  |//  //|      |//  //|      |//  //|      |//  //|      |\n"
"  |//////|      |//////|      |//////|      |//////|      |\n"
"  ---------------------------------------------------------\n"
"  |      |//////|      |//////|      |//////|      |//////|\n"
"  |      |//  //|      |//  //|      |//  //|      |//  //|\n"
" 2|  "<<board[1][0]<<"  |- "<<board[1][1]<<" -|  "<<board[1][2]<<"  |- "<<board[1][3]<<" -|  "<<board[1][4]<<"  |- "<<board[1][5]<<" -|  "<<board[1][6]<<"  |- "<<board[1][7]<<" -|\n"
"  |      |//  //|      |//  //|      |//  //|      |//  //|\n"
"  |      |//////|      |//////|      |//////|      |//////|\n"
"  ---------------------------------------------------------\n"
"  |//////|      |//////|      |//////|      |//////|      |\n"
"  |//  //|      |//  //|      |//  //|      |//  //|      |\n"
" 1|- "<<board[0][0]<<" -|  "<<board[0][1]<<"  |- "<<board[0][2]<<" -|  "<<board[0][3]<<"  |- "<<board[0][4]<<" -|  "<<board[0][5]<<"  |- "<<board[0][6]<<" -|  "<<board[0][7]<<"  |\n"
"  |//  //|      |//  //|      |//  //|      |//  //|      |\n"
"  |//////|      |//////|      |//////|      |//////|      |\n"
"  ---------------------------------------------------------\n"
"     A      B      C      D      E      F      G      H    \n";


    }







      int main()
{pawn p("a2",'w');
pawn p2("b2", 'w');
pawn p3 ("c2", 'w');
pawn p4 ("d2", 'w');

 int index;
 vector <pawn> pwn;
 string move;

pwn.push_back(p);
pwn.push_back(p2);
pwn.push_back(p3);
pwn.push_back(p4);



string board[8][8]=
{"//",   "  ",   "//",   "  ",   "//",   "  ",   "//",   "  ",

 "  ",   "//",   "  ",   "//",   "  ",   "//",   "  ",   "//",

 "//",   "  ",   "//",   "  ",   "//",   "  ",   "//",   "  ",

 "  ",   "//",   "  ",   "//",   "  ",   "//",   "  ",   "//",

 "//",   "  ",   "//",   "  ",   "//",   "  ",   "//",   "  ",

 "  ",   "//",   "  ",   "//",   "  ",   "//",   "  ",   "//",

 "//",   "  ",   "//",   "  ",   "//",   "  ",   "//",   "  ",

 "  ",   "//",   "  ",   "//",   "  ",   "//",   "  ",   "//"

};



for (int i=0; i<pwn.size(); i++) pwn[i].setOnBoard(board);



displayBoard(board);

cout<<endl<<endl<<"Your MOVE?"<<endl;

cin>>move; //Unosi se u formatu  kao na primer a2a3


string from=move.substr(0,2);

index=whatPiece(from,pwn);

string to=move.substr(2,2);


pwn[index].move(to, board);
system("cls");

displayBoard(board);


cin>>move;
from=move.substr(0,2);

index=whatPiece(from,pwn);

to=move.substr(2,2);

pwn[index].move(to, board);
system("cls");

displayBoard(board);







  return 0;



  }



Znam da ne treba da koristim system funkciju ali ne volim kako se prikazuje bez nje.

Takodje, ovakva implementacija moze da prodje ako je za moje sopstvene potrebe.

Prava implementacija podrazumeva da programer koji koristi klasu ima slobodu da predstavi tablu i figure prema svojoj zamisli. To cu da radim kada zavrsim ovu verziju.
[ vatri @ 14.12.2011. 08:47 ] @
Code:

...
Pawn(POSITION startPos) : ChessPiece(startPos)
                                         , m_type(PT_Pawn)
...



Samo jedno pitane - sta znaci ovo iza " : " razdvojeno sa " , " ?

Jel to znaci da inicijalizujemo ChessPiece i m_type i kako se to koristi kasnije (kako dodjelimo vrijednosti startPos i PT_Pawn objektu) ?
[ glorius @ 15.12.2011. 17:18 ] @
Ovo je drugi nacin ( preporucujem ga ) za inicijalizaciju promenljivih.

Prvi nacin ti je, verovatno, poznat (objasnicu na jednostavnijem primeru).

Code:


class Point
{
public:
     Point(float x, float y);
private:
     float m_x;
     float m_y;
};

// prvi nacin
Point::Point(float x, float y)
{
        m_x = x;
        m_y = y;
}

// drugi nacin
Point::Point(float x, float y) : m_x(x), m_y(y)
{
        
}



Zamisli sad da su m_x, m_y neki objekti (umesto float).

m_x(x) znaci da se poziva konstruktor kopije za taj objekat.

A poziv m_x = x prvo implicitno konstruise m_x ( ne vidi se u kodu ali se poziva konstruktor ) pa onda poziva operator=.

Ako su u pitanju veliki objekti konstruisanje plus operator= moze biti skupo i zato se ovakav nacin inicijalizacije m_x(x) preferira.
[ vatri @ 16.12.2011. 07:36 ] @
Sad je puno jasnije kad si dao ovako jednostavan primjer.

Malo me zbunilo ovo "m_type(PT_Pawn)" jer nisam obracao paznju da je PT_Pawn element iz PieceType, a ne varijabla kao u primjeru "ChessPiece(startPos)"

Hvala !