// tempapp.cpp ////////////////////////////////////////////////////////////////////////////// // Simple solitare came to study inheritance // Made by using Little Application framework by Timothy P. Justice // Vesa Lappalainen modified 11.8.1993 the example code // + little more general cardPile -class // + possibly empty card in pile as a placeholder // + addCard can add to n:th place // + more methods (suit, rank, color...) // + virtual select and virtual emptySelect // + as little public-variables as possible (none) // + deckPile: // + autotomatic deal // + empty deck fill's itself from discard pile // To change: // - lot of constants around program // - piles are globals // - select-methods points to it's sister? // - total redraw not good in slow machines // - game not ready #include "card.h" //---------------------------------------------------------------------------- template class Link { // One card in cardPile is T value_v; // pointer to the card Link *next_v; // and pointer to the next public: Link(T nvalue, Link *link_v) { value_v = nvalue; next_v=link_v; } T value() { return value_v; } Link *next() { return next_v; } void add(T newval) { this->next_v = new Link(newval,this->next_v); } }; // cardLink /////////////////// cardPile to inherit other piles ////////////////////////// class cardPile { // rank, suit etc. for pile is the prop. for topmost card POINTT upper; // Piles's upper left corner Link *firstLink; // Pointer to first card public: cardPile(int x,int y,int doempty=0) { // To every pile it is possible to add upper=POINTT(x,y); // an empty card to hold place after pile firstLink = NULL; // is finnished. If doselect is done if ( !doempty ) return; // then virtual select is called for card *empty = new card(0,0); // none empty pile and virtual emptySelect if ( doempty == 2 ) empty->flip(); // for empty pile. If doempty==1 empty->setColor(gray); // then empty card is reversed, if ==2 cardPile::addCard(empty); // it's faceUp. Allways gray } int empty() { return ( !firstLink || !rank() ); } card *top() { return (firstLink ? firstLink->value() : NULL ); } card *flip() { card *t=top(); return ( t ? t->flip() : NULL ); } # define TOPPROP(prop) int prop() { card *t=top(); return (t ? t->prop() : 0); } TOPPROP(rank); // int rank(); TOPPROP(suit); TOPPROP(faceUp); TOPPROP(color); # undef TOPPROP virtual card *topCard() { // Take top card away and return it or if ( empty() ) return NULL; // return NULL for empty pile Link *p = firstLink; card *q = p->value(); firstLink = firstLink->next(); delete p; return q; } int includes(int x, int y); virtual void addCard(card *newCard,int n=0); virtual void display(window *w) { if ( firstLink ) top()->draw(w); } virtual void select() {}; virtual void emptySelect() {}; virtual void doselect() {if ( empty() ) emptySelect(); else select(); } virtual int canTake(card *c) { return 0; } }; // cardPile --------------------------------------------------------------- void cardPile::addCard(card *newCard, int n) { // Add card to n:th position newCard->moveTo(upper); // Place the card to deck's pos. if ( n == 0 ) { // If insert to begining firstLink = new Link(newCard, firstLink); return; } Link *p = firstLink; // Othervise skip n-1 card while ( --n > 0 ) if ( p->next() ) p = p->next(); p->add(newCard); // and place after that. } int cardPile::includes(int x, int y) // Point (x,y) is included { // to pile if included for (Link *p = firstLink; p != NULL; p = p->next() ) // to any card if ( (p->value())->includes(x,y) ) return 1; return 0; } /////////////////// cardPile ready /////////////////////////////////////////// /////////////////// child piles ////////////////////////////////////////////// //---------------------------------------------------------------------------- class deckPile : public cardPile { // Pile to deal card's int count; // Number of card's in pile public: deckPile(int x,int y) : cardPile(x,y,2) { count = 0; deal(); } virtual card *topCard() { // Remember decrease count if ( empty() ) return NULL; // when topmost is taken count--; return cardPile::topCard(); } virtual void addCard(card *newCard,int n=0) {// Add to random place if ( n ) n = randomInt(0,count); // if n!=0, else to beg. cardPile::addCard(newCard,n); // count++; // And remember add count } // when new is coming void emptySelect(); void select(); void deal(); }; // deckPile void deckPile::deal() { for (int s=1; s <= 4; s++) for (int r=1; r<=13; r++) addCard(new card(0,0,s,r),1); // n=1 -> add to random place } //---------------------------------------------------------------------------- class suitPile : public cardPile { // Pile for card's in right public: // place suitPile(int x, int y):cardPile(x,y,1) {} int canTake(card *c) { // Empty takes A, other same suit, one bigger rank if ( empty() ) return ( c->rank() == 1 ? TRUE : FALSE ); if ( c->suit() == suit() && c->rank() == rank() +1 ) return TRUE; return FALSE; } }; // suitPile //---------------------------------------------------------------------------- class discardPile : public cardPile { // Pile to look topmost public: // from deck discardPile(int x, int y):cardPile(x,y) {}; void select(); }; // discardPile //---------------------------------------------------------------------------- class tablePile : public cardPile { // Pile from where cards public: // are taken or where tablePile(int x, int y):cardPile(x,y) {}; // placed on the table int canTake(card *c) { // Empty takes K, other opposite color, 1 smaller rank if ( empty() ) return ( c->rank() == 13 ? TRUE : FALSE ); if ( c->color() != color() && c->rank() == rank()-1 ) return TRUE; return FALSE; } void select(); }; // tablePile /////////////////// Globals (yak) //////////////////////////////////////////// deckPile theDeck(480,100); discardPile theDiscard(400,100); suitPile suits[4] = { suitPile(50,100), suitPile(130,100), suitPile(210,100), suitPile(290,100) }; tablePile table[7] = { tablePile( 0,200), tablePile( 80,200), tablePile(160,200), tablePile(240,200), tablePile(320,200), tablePile(400,200), tablePile(480,200) }; cardPile *allPiles[13]; int somebodyTake(card *c, cardPile *p) // If card is accepted in any { // pile except p, it's added there for ( int i=2; i<13; i++) // and 1 is returned, otherwise 0 if ( allPiles[i] != p ) if ( allPiles[i]->canTake(c) ) { allPiles[i]->addCard(c); return 1; } return 0; } //////////////////// Select -methods: //////////////////////////////////////// void deckPile::select() { card *c = topCard(); if ( !c ) return; theDiscard.addCard(c->flip()); } void discardPile::select() { card *c = topCard(); if ( !c ) return; if ( !somebodyTake(c,NULL) ) addCard(c); } void tablePile::select() { card *c = topCard(); if ( !c ) return; if ( !c->faceUp() ) { addCard(c->flip()); return; } if ( !somebodyTake(c,this) ) addCard(c); } void deckPile::emptySelect() { card *c; while ( ( c = theDiscard.topCard() ) != NULL ) addCard(c->flip()); } /////////////////// just subrutines to do some initializion ////////////////// void initGame() { int i,j,k=0; allPiles[k++] = &theDeck; allPiles[k++] = &theDiscard; for (i=0; i<4; i++) allPiles[k++] = &suits[i]; for (i=0; i<7; i++) allPiles[k++] = &table[i]; for (i=0; i<7; i++) for (j=0; j<=i; j++) table[i].addCard(theDeck.topCard()); for (i=0; i<7; i++) table[i].flip(); } /////////////////// application ////////////////////////////////////////////// class gameApplication : public application { public: gameApplication(char *apName, char *apTitle, HANDLE thisInst, HANDLE prevInst): application(apName, apTitle, thisInst, prevInst){ initGame(); }; void mouseDown(int,int); void paint(); }; // gameApplication void gameApplication::mouseDown(int x,int y) { for (int i=0; i<13; i++) if ( allPiles[i]->includes(x,y) ) { allPiles[i]->doselect(); break; } clearAndUpdate(); } void gameApplication::paint() { for (int i=0; i<13; i++) allPiles[i]->display(this); } ////////////////////////////////////////////////////////////////////////////// int PASCAL WinMain(HANDLE thisInst, HANDLE prevInst, LPSTR, int) { gameApplication theApp("PENS","Game Application",thisInst,prevInst); return theApp.run(); }