2012-11-28 53 views
0

所以我有兩個並排的遊戲。使用Extern的鏈接器問題

proj2/main.cpp (main that gets run that then can call either game) 
proj2/spades/display.cpp 
proj2/spades/gameplay.cpp 
proj2/spades/otherFiles.cpp 
proj2/hearts/display.cpp (this is the same display class as in the spades game with the same functions just sightly altered.) 
proj2/hearts/hearts.cpp 
proj2/hearts/otherFiles.cpp 

我得到以下鏈接器錯誤,

./gamePlay.o: In function `__static_initialization_and_destruction_0(int, int)': 
gamePlay.cpp:(.text+0x396): undefined reference to `spades::display::display()' 
./gamePlay.o: In function `__tcf_3': 
gamePlay.cpp:(.text+0x480): undefined reference to `spades::display::~display()' 
在我gamePlay.cpp文件I定義以下

,我認爲這是我的錯誤是,

display monitor; 

如果我將extern標識符添加到行如

extern display monitor; 

錯誤時纔會消失,產生了以下問題,

./gamePlay.o: In function `spades::gamePlay::storeBid(std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&)': 
    gamePlay.cpp:(.text+0x14ee): undefined reference to `spades::monitor' 
    gamePlay.cpp:(.text+0x14f3): undefined reference to `spades::display::drawBox(int, int, int, int, int)' 

我認爲這個錯誤是由以下這些行這個未來,但我不知道如何解決這個錯誤。感覺現在完全迷失了。 (我不明白爲什麼我需要extern作爲監視器的標識符)。還包括所有的內容應該沒問題。

int key = monitor.captureInput(); 
     monitor.drawBox(2, 5, 3, 2, 0); 

下面是我的display.h文件

/* 
* Description: Defines constants and class prototypes and variables 
*/ 

// These are include files they are used for accessing functions and 
// variables in external libraries. 
#include <ncursesw/ncurses.h> 
#include <iostream> 
#include <cstdio> 
// This is the namespace std, without this you would need to add "std::" 
// infront of every variable and function from the std library. 
//using namespace std; 

// These Mouse Mask Definitions are for some of the common mouse buttons 
// that are used in this project. 
#define LEFT_UP 1 
#define LEFT_DOWN 2 
#define LEFT_CLICK 4 
#define LEFT_DOUBLECLICK 24 

#define RIGHT_UP 4096 
#define RIGHT_DOWN 8192 
#define RIGHT_CLICK 16384 
#define RIGHT_DOUBLECLICK 32768 

#define MIDDLE_ROLLUP 1048576 
#define MIDDLE_ROLLDOWN 256 
namespace spades { 
// Some extended character definitions for showing the special symbols 
// in the extended UTF-8 character map. 
const char joker[] = {0xE2, 0x98, 0xBA, 0}; 
const char clubs[] = {0xE2, 0x99, 0xA3, 0}; 
const char diamonds[] = {0xE2, 0x99, 0xA6, 0}; 
const char hearts[] = {0xE2, 0x99, 0xA5, 0}; 
const char spades[] = {0xE2, 0x99, 0xA0, 0}; 

/* 
* This is the display class definitions 
*/ 
class display { 
public: 
    /* "constructor" 
    * This function is called whenever a new object of class display is first 
    * created. Put initialization functions in here. 
    */ 
    display(void){}; 
    /* "destructor" 
    * This function is called just before a object is deleted. Put clean up 
    * functions in here. 
    */ 
    ~display(){}; // destructor 

    // captures user input 
    int captureInput(void); 
    // stores new screensize on update 
    void handleResize(int sig); 

    /* 
    * Drawing commands 
    */ 
    // display a card on the screen 
    void displayCard(int x, int y, int suit, int number, int printAtt); 
    // erase in the shape of a box on the screen 
    void eraseBox(int x, int y, int sizeX, int sizeY); 
    // draw a box on the screen 
    void drawBox(int x, int y, int sizeX, int sizeY, int printAtt); 
    // display banner text at the bottom of the screen 
    void bannerBottom(std::string bannerText); 
    void bannerAboveBottom(std::string bannerText); 
    // display banner text at the top of the screen 
    void bannerTop(std::string bannerText); 

    // get information about the display 
    int getCols(void) {return cols;} 
    int getLines(void) {return lines;} 
    int getMouseEventX(void) {return mouseEventX;} 
    int getMouseEventY(void) {return mouseEventY;} 
    int getMouseEventButton(void) {return mouseEventButton;} 

    // Updates the screen after you finish drawing 
    void updateScreen(void) {refresh();} 

    // sets an offset for when cards clip the bottom of the screen 
    void setBottomOffset(int offset) {lineBoundaryOffset=offset;} 

private: 
    // These are private functions and variables used inside of display. 
    // You should not try to access these from outside the display class. 
    void printFace(int suit, int number, int line, int printAtt); 
    void printSuit(int suit); 
    void printNumber(int number); 

    int cols; 
    int lines; 
    int mouseEventX; 
    int mouseEventY; 
    int mouseEventButton; 
    int lineBoundaryOffset; 
}; 
} 

下面是我的display.cpp文件

/* 
* Description: Defines the functionality of the user interface. 
* 
* NOTES: 
*  * Requires the terminal (Putty) to be set to UTF-8. 
*  * Does not function when running a screen session. 
*/ 
#include <iostream> 
#include <sys/ioctl.h> 
#include <cstdio> 
#include <unistd.h> 
#include <locale.h> 
#include <ncursesw/ncurses.h> 

#include "display.h" 
namespace spades { 
//using namespace std; 

/* Function: This is the constructor. 
* Description: It is called whenever an object of class display is initialized 
*/ 
display::display(void) { 
    /* Initilization of Terminal */ 
    // required to get card suits displaying, combined with UTF-8 set in terminal 
    setlocale(LC_ALL,"en_US.utf-8"); 

    // initialize ncurses screen 
    initscr(); 
    // allow for color settings 
    start_color(); 
    // clear the screen 
    clear(); 
    // turn off the keyboard echo (reqiured while drawing) 
    noecho(); 
    // Change to character mode (so individual characters are being read at a 
    // time rather than waiting for a carriage return). 
    cbreak(); 
    // Allows for function keys to be used (also nessacary for getting the mouse 
    // movement working). 
    keypad(stdscr, TRUE); 
    // set which mouse events are captured 
    mousemask(ALL_MOUSE_EVENTS, NULL); 
    // Setting the timeout for the capture input values are in 1/10ths of a second. 
    halfdelay(5); 

    // setup the screen size settings. 
    cols = 80; 
    lines = 24; 
    // this updates the locally stored col and line variables 
    handleResize(0); 
    // set a no card draw offset of 1 so the bottom banner is not overwritten 
    lineBoundaryOffset = 1; 

    // Settings for card colors (these can be set outside of the display class) 
    init_pair(1, COLOR_CYAN, COLOR_BLACK); // for card outline 
    init_pair(2, COLOR_BLUE, COLOR_BLACK); // for spades and clubs 
    init_pair(3, COLOR_RED, COLOR_BLACK); // for hearts and diamonds 
    init_pair(4, COLOR_GREEN, COLOR_BLACK); // for turned over card 
    init_pair(5, COLOR_GREEN, COLOR_BLACK); // for box drawing 
    init_pair(6, COLOR_GREEN, COLOR_BLACK); // for banner display 
} 

/* Function: This is the destructor. 
* Description: This is called just before an object is deleted. 
*/ 
display::~display() { 
    // this is turns off all the special settings and returns the terminal to normal 
    endwin(); 
    // insert deletion of dynamically created objects here too 
} 

/* 
* Function: This captures all the userinput. 
* Description: It captures mouse and keyboard events. 
*  Returns "Positive Number" 
*   - for user keypress 
*   - this is a character code typed 
*  Returns "0" - for no user input 
*   - this is when nothing is typed for half a second 
*   - allows for other timed operations to occur 
*  Returns "-1" - for mouse event 
*   - details of the mouse event must be fetched from this class 
*   - use getMouseEventX, getMouseEventY and getMouseEventButton 
*/ 
int display::captureInput(void) { 
    // obtain one mouse event or keypress 
    int ch=getch(); 
    // this is a switch statement for the result of getch 
    switch (ch) { 
    case KEY_MOUSE: // this occurs when an mouse event occurs 
     { 
     MEVENT mevent; // this is a variable declared of type MEVENT 
     getmouse(&mevent); // this gets the mouse event from ncurses (library) 
     mouseEventX = mevent.x; // get the column location of the event 
     mouseEventY = mevent.y; // get the row location of the event 
     mouseEventButton = mevent.bstate; // get the button state of the mouse 
     return -1; // -1 is for a mouse event 
     } 
     break; 
    case ERR: // this occurs when there is a timeout 
     { 
     return 0; // 0 is when nothing occurs 
     } 
     break; 
    default: // this occurs when a key is pressed 
     return ch; // a character is when the user types something 
    } 

    return 0; // this is never called, but is used to stop compiler complaints 
} 

/* 
* Function: Updates all the information in the display class on window resize 
* Description: This function just updates information, it requires the call 
*  from a static singal handler. Signal handlers service interrupts and require 
*  a static function to be called, because they are not part of the main 
*  program control flow. The signal handler should be declared in the main 
*  class, because your game should redraw the display on a resize. 
*/ 
void display::handleResize(int sig) { 
#ifdef TIOCGSIZE // operating system dependant differences 
    struct ttysize ts; 
    ioctl(STDIN_FILENO, TIOCGSIZE, &ts); // get the information of the terminal 
    cols = ts.ts_cols; 
    lines = ts.ts_lines; 
#elif defined(TIOCGWINSZ) 
    struct winsize ts; 
    ioctl(STDIN_FILENO, TIOCGWINSZ, &ts); // get the information of the terminal 
    cols = ts.ws_col; 
    lines = ts.ws_row; 
#endif /* TIOCGSIZE */ 
    resizeterm(lines, cols); // sets the ncurses window size correctly 
} 

/* 
* Function: Displays various cards on the game screen 
* Description: This function displays various playing cards on the screen. 
*  The first two arguments are the x and y coordinates of the top left corner 
*  of the card. 
*   The suit values are: 1=spades, 2=hearts, 3=clubs, 4=diamonds 
*   The numbers are: 1=Ace, 2-10=2-10, 11=Jack, 12=Queen, 13=King, 14=Joker 
*  Any suit and number that do not match the valid numberrs generates a face down 
*  card. 
*   The printAtt allows for one or more any of the following display settings: 
*    A_NORMAL  Normal display (no highlight) 
*    A_STANDOUT  Best highlighting mode of the terminal. 
*    A_UNDERLINE  Underlining 
*    A_REVERSE  Reverse video 
*    A_BLINK   Blinking 
*    A_DIM   Half bright 
*    A_BOLD   Extra bright or bold 
*    A_PROTECT  Protected mode 
*    A_INVIS   Invisible or blank mode 
*    A_ALTCHARSET Alternate character set 
*    A_CHARTEXT  Bit-mask to extract a character 
*    COLOR_PAIR(n) Color-pair number n 
*/ 
void display::displayCard(int x, int y, int suit, int number, int printAtt) { 

    // Ncurses drawing settings 
    attron(COLOR_PAIR(1) | printAtt); 
    // prevent draw if it off the screen 
    if (x>=0 && y>=0 && x<cols-6 && y<lines-lineBoundaryOffset) { 
     // print the top lines of the card 
     mvprintw(y,x,"\u250c\u2500\u2500\u2500\u2500\u2510"); 
     // the next 4 if statements prevent draw if it is over the bottom of the screen 
     if (y<lines-1-lineBoundaryOffset) { 
      move(y+1,x); // move command 
      printFace(suit,number,0, printAtt); // call function to print card face 
     } 
     if (y<lines-2-lineBoundaryOffset) { 
      move(y+2,x); // move command 
      printFace(suit,number,1, printAtt); // call function to print card face 
     } 
     if (y<lines-3-lineBoundaryOffset) { 
      move(y+3,x); // move command 
      printFace(suit,number,2, printAtt); // call function to print card face 
     } 
     if (y<lines-4-lineBoundaryOffset) { 
      // prints the bottom lines of the card 
      mvprintw(y+4,x,"\u2514\u2500\u2500\u2500\u2500\u2518"); 
     } 
    } 
    // Ncurses turn off the drawing settings 
    attroff(COLOR_PAIR(1) | printAtt); 
} 

/* 
* Function: Print a single line of what is written on the card. 
* Description: This copies suit, number and printAtt from the calling function. 
*  Also includes what line of the card face is being drawn. 
*/ 
void display::printFace(int suit, int number, int line, int printAtt) { 
    // draw left edge of the card 
    printw("\u2502"); 

    if (suit==2 || suit==4) { // Red for Hearts and Diamonds 
     attron(COLOR_PAIR(3) | printAtt); 
    } else { // Black for Spades and Clover 
     attron(COLOR_PAIR(2) | printAtt); 
    } 

    // this the display of the joker 
    if (number==14) { 
     if (line==0) 
      printw("J%s ", joker); 
     if (line==1) 
      printw("oker"); 
     if (line==2) 
      printw(" J%s", joker); 
    // this is the display for the cards with suits and numbers 
    } else if (suit>=1 && suit <=4 && number>=1 && number<=13) { 
     if (line==0) { 
      printSuit(suit); // function to draw suit 
      printNumber(number); // function to draw number 
      if (number!=10) 
       printw(" "); 
      printw(" "); 
     } else if (line==2) { 
      if (number!=10) 
       printw(" "); 
      printw(" "); 
      printNumber(number); // function to draw number 
      printSuit(suit); // function to draw suit 
     } else { 
      printw(" "); 
     } 
    // this is for a face down card 
    } else { 
     // the face down cards have a special color 
     attron(COLOR_PAIR(4) | printAtt); 
     if (line==0) 
      printw("%s %s", spades, hearts); 
     if (line==1) 
      printw("Play"); 
     if (line==2) 
      printw("%s %s", diamonds, clubs); 
     attroff(COLOR_PAIR(1) | printAtt); 
    } 

    // turn on the card edge color settings 
    attron(COLOR_PAIR(1) | printAtt); 
    // print the right edge of the card 
    printw("\u2502"); 
} 

/* 
* Function: Print the suit of the card 
* Description: This is just a look up table. 
*/ 
void display::printSuit(int suit) { 
    switch (suit) { 
     case 1: 
      printw("%s",spades); 
      break; 
     case 2: 
      printw("%s",hearts); 
      break; 
     case 3: 
      printw("%s",clubs); 
      break; 
     case 4: 
      printw("%s",diamonds); 
      break; 
     default: 
      printw(" "); 
      break; 
    } 
} 

/* 
* Function: Prints the number on the card 
* Description: This is just a look up table. 
*/ 
void display::printNumber(int number) { 
    switch (number) { 
     case 2: 
     case 3: 
     case 4: 
     case 5: 
     case 6: 
     case 7: 
     case 8: 
     case 9: 
     case 10: 
      printw("%i",number); 
      break; 
     case 1: 
      printw("%c",'A'); 
      break; 
     case 11: 
      printw("%c",'J'); 
      break; 
     case 12: 
      printw("%c",'Q'); 
      break; 
     case 13: 
      printw("%c",'K'); 
      break; 
     default: 
      printw(" "); 
      break; 
    } 
} 

/* 
* Function: Erases a rectangle on the screen 
* Description: x,y is for the top left corner, sizeX and sizeY set 
*   how big the square is. 
*/ 
void display::eraseBox(int x, int y, int sizeX, int sizeY) { 
    std::string strDraw; 
    int yCount; 
    int maxSizeX; 

    // this limits the column size of the draw when it is over the edge 
    // of the drawing area 
    if (sizeX+x > cols) 
     maxSizeX=cols-x; 
    else 
     maxSizeX=sizeX; 

    // for the number of rows that need to be drawn 
    for (yCount=0; yCount<sizeY;yCount++) { 
     // if the box goes over the edge of the drawable screen 
     // stop drawing by breaking the loop 
     if (yCount+y > lines-lineBoundaryOffset || y < 0) 
      break; 
     // reset the line to be drawn 
     strDraw = ""; 
     // check that x is not off the screen 
     if (x<=cols && x >= 0) { 
      // make a string needed for box width 
      strDraw.append(maxSizeX,' '); 
      // print the line of the box 
      mvprintw(y+yCount,x,"%s",strDraw.c_str()); 
     } 
    } 
} 

/* 
* Function: Draws a box on the screen 
* Description: x,y is for the top left corner, sizeX and sizeY set 
*   how big the square is. printAtt allows for changes in the 
*   display settings. 
*/ 
void display::drawBox(int x, int y, int sizeX, int sizeY, int printAtt) { 
    std::string strDraw; 
    int ii; 
    int yCount; 

    // set the box setting colors on 
    attron(COLOR_PAIR(5) | printAtt); 

    // for the box height being drawn loop 
    for (yCount=0; yCount<sizeY;yCount++) { 
     // break loop if the drawing is offscreen 
     if (yCount+y > lines-lineBoundaryOffset || y < 0) 
      break; 
     // if x is on the screen 
     if (x<=cols) { 
      strDraw = ""; 
      // for the box width loop 
      for (ii=0;ii<sizeX;ii++){ 
       // stop drawing if the x is offscreen 
       if (ii+x > cols || x < 0) 
        break; 
       // first line 
       if (yCount==0) { 
        if (ii==0) { 
         strDraw.append("\u250c"); // left 
        } else if (ii==sizeX-1) { 
         strDraw.append("\u2510"); // right 
        } else { 
         strDraw.append("\u2500"); // middle 
        } 
       // last line 
       } else if (yCount==sizeY-1) { 
        if (ii==0) { 
         strDraw.append("\u2514"); // left 
        } else if (ii==sizeX-1) { 
         strDraw.append("\u2518"); // right 
        } else { 
         strDraw.append("\u2500"); // middle 
        } 
       // other lines 
       } else { 
        if (ii==0) { 
         strDraw.append("\u2502"); // left 
        } else if (ii==sizeX-1) { 
         strDraw.append("\u2502"); // right 
        } else { 
         strDraw.append(" "); // middle 
        } 
       } 
      } 
      // print the line that was created 
      mvprintw(y+yCount,x,"%s",strDraw.c_str()); 
     } 
    } 
    // turn off the attribute colors 
    attroff(COLOR_PAIR(5) | printAtt); 
} 

/* 
* Function: Draws a banner of text at the bottom right of the screen 
* Description: Inverts the color and draws the banner at the bottom 
*  of the screen. Does not handle carriage returns on the string. 
*/ 
void display::bannerBottom(std::string bannerText) { 
    // change to the banner draw settings 
    attron(COLOR_PAIR(6) | A_REVERSE | A_BOLD); 
    // checks if the banner string size is smaller than the width of the screen 
    if((unsigned)cols > bannerText.size()) { 
     // moves the cursor to the bottom of the screen 
     move(lines-1,0); 
     // fill in extra space to the banner text is right adjusted 
     hline(' ',cols - bannerText.size()); 
     // prints out the banner text 
     mvprintw(lines-1,cols-bannerText.size(),"%s", bannerText.c_str()); 
    // if banner string size is larger than width of screen 
    } else { 
     // clip the banner text so it doesn't wrap over to the next line 
     mvprintw(lines-1,0,"%s", (bannerText.substr(0,cols)).c_str()); 
    } 
    // turn off the draw colors 
    attroff(COLOR_PAIR(6) | A_REVERSE | A_BOLD); 
} 

void display::bannerAboveBottom(std::string bannerText) { 
    // change to the banner draw settings 
    attron(COLOR_PAIR(1) | A_REVERSE | A_BOLD); 
    // checks if the banner string size is smaller than the width of the screen 
    if((unsigned)cols > bannerText.size()) { 
     // moves the cursor to the bottom of the screen 
     move(lines-2,0); 
     // fill in extra space to the banner text is right adjusted 
     hline(' ',cols - bannerText.size()); 
     // prints out the banner text 
     mvprintw(lines-2,cols-bannerText.size(),"%s", bannerText.c_str()); 
    // if banner string size is larger than width of screen 
    } else { 
     // clip the banner text so it doesn't wrap over to the next line 
     mvprintw(lines-2,0,"%s", (bannerText.substr(0,cols)).c_str()); 
    } 
    // turn off the draw colors 
    attroff(COLOR_PAIR(1) | A_REVERSE | A_BOLD); 
} 

/* 
* Function: Draws a banner of text at the top left of the screen 
* Description: Inverts the color and draws the banner at the top 
*  of the screen. Does not handle carriage returns on the string. 
*/ 
void display::bannerTop(std::string bannerText) { 
    // change to the banner draw settings 
    attron(COLOR_PAIR(6) | A_REVERSE | A_BOLD); 
    // checks if the banner string size is smaller than the width of the screen 
    if((unsigned)cols > bannerText.size()) { 
     // moves the cursor to the bottom of the screen 
     move(0,0); 
     // prints out the banner text 
     printw("%s", bannerText.c_str()); 
     // fill in extra space after the banner text 
     hline(' ',cols - bannerText.size()); 
    // if banner string size is larger than width of screen 
    } else { 
     // clip the banner text so it doesn't wrap over to the next line 
     mvprintw(0,0,"%s", (bannerText.substr(0,cols)).c_str()); 
    } 
    // turn off the draw colors 
    attroff(COLOR_PAIR(6) | A_REVERSE | A_BOLD); 
} 
} 

下面是我的gameplay.h文件

#include "player.h" 
#include "display.h" 

#ifndef gamePlay_H 
#define gamePlay_H 
namespace spades { 

class gamePlay{ 

    bool spadesBroken; 

public: 
    vector <spades::card> getDeck(); 
    vector <spades::player>getplayers(); 
    bool getSpadesBroken() {return spadesBroken;} 
    void setSpadesBroken(bool b){spadesBroken = b;} 

    int compareCenter(int leadplayer); 
    void createDeck(); 
    void deal(vector <spades::card> &deck, vector <spades::player> &players); 
    void handSort(); 
    bool containSuit(spades::card lead, spades::player players); 
    bool onlySpade(spades::player play); 

    int handCheck(int xevent, int yevent, vector <spades::player> players, int trickStart); 

    void displayHand(); 
    void displayAdd(); 
    void humanPlay(int trickStart); 
    void CPUplay(int trickStart, int CPU); 
    void score(spades::player &play, spades::player &play2); 
    void storeBid(stringstream &msg); 
    void runGame(); 

}; 
} 
#endif 

以下是我的gameplay.cpp文件

#include <iostream> 
#include <sys/ioctl.h> 
#include <cstdio> 
#include <unistd.h> 
#include <locale.h> 
#include <ncursesw/ncurses.h> 
#include <fstream> 


#include "gamePlay.h" 
#include <cstdlib> 
#include <sstream> 
#include <ctime> 
namespace spades { 
vector <spades::player> players(4); 
vector <spades::card> deck(52); 
display monitor; 
card center[4]; 

vector <spades::card> gamePlay::getDeck(){return deck;} 
vector <spades::player> gamePlay::getplayers(){return players;} 

//sorts the cards in the players hand into diamonds, clubs, hearts, spades 
void gamePlay::handSort(){ 
    int spades[13]; 
    int hearts[13]; 
    int clubs[13]; 
    int diamonds[13]; 
    int index; 
    int i; 
    for(i=0; i<13; i++){ //determines the card number and places them into corresponding indexes 
     index = (players.at(0).hand.at(i).getCardNum()+11)%13; //cause the cards to be placed based on their number with 2 being index 0 and 1(ace) being index 12 
     switch(players.at(0).hand.at(i).getSuit()) 
     { 
     case 1: spades[index] = 1; 
     break; 
     case 2: hearts[index] = 1; 
     break; 
     case 3: clubs[index] = 1; 
     break; 
     case 4: diamonds[index] = 1; 
     break; 
     default: mvprintw(3,2,"!!!!!!!we have a problem!!!!!!!!!!"); 
     break; 
     } 
    } 
    i = 0; 
    while(i<13){ //being placing the ordered cards back into the players hand 
     int j = 0; 
     while(j < 13){ 
      if(diamonds[j] == 1){ //if a card has been placed in this index for the diamonds only array 
       if(j+2 == 14) //if the card is an ace 
        players.at(0).hand.at(i).setCardNum(1); 
       else 
        players.at(0).hand.at(i).setCardNum(j+2); //add 2 to each index to get the card number 
       players.at(0).hand.at(i).setSuit(4); 
       i++; 
      } 
      j++; 
     } 
     j = 0; 
     while(j < 13){ 
      if(clubs[j] == 1){ 
       if(j+2 == 14) 
        players.at(0).hand.at(i).setCardNum(1); 
       else 
        players.at(0).hand.at(i).setCardNum(j+2); 
       players.at(0).hand.at(i).setSuit(3); 
       i++; 
      } 
      j++; 
     } 
     j = 0; 
     while(j < 13){ 
      if(hearts[j] == 1){ 
       if(j+2 == 14) 
        players.at(0).hand.at(i).setCardNum(1); 
       else 
        players.at(0).hand.at(i).setCardNum(j+2); 
       players.at(0).hand.at(i).setSuit(2); 
       i++; 
      } 
      j++; 
     } 
     j = 0; 
     while(j < 13){ 
      if(spades[j] == 1){ 
       if(j+2 == 14) 
        players.at(0).hand.at(i).setCardNum(1); 
       else 
        players.at(0).hand.at(i).setCardNum(j+2); 
       players.at(0).hand.at(i).setSuit(1); 
       i++; 
      } 
      j++; 
     } 
    } 
} 

//compares the center pile of 4 played cards to determine who wins the trick 
int gamePlay::compareCenter(int leadplayer){ 
    int highest = center[leadplayer].getCardNum(); 
    if(center[leadplayer].getCardNum() == 1) 
     highest = 14; 
    int suit = center[leadplayer].getSuit(); 
    int player = leadplayer; 

    for(int i = leadplayer+1; i < leadplayer+4; i++) 
    { 
     if(center[i%4].getSuit() == 1) 
      setSpadesBroken(true); 
     if((suit != 1) && (center[i%4].getSuit() == 1)) 
     { 
      player = i%4; 
      suit = 1; 
      highest = center[i%4].getCardNum(); 
     } 
     if(suit == center[i%4].getSuit()){ 
      if(center[i%4].getCardNum() == 1){ 
       player = i % 4; 
       highest = 14; 
      } 
      if(highest < center[i%4].getCardNum()) 
      { 
       player = i%4; 
       highest = center[i%4].getCardNum(); 
      } 
     } 
    } 
    players.at(player).setTricksTaken(players.at(player).getTricksTaken()+1); //increments the trick count of the winning player 
    return player; //return the player who won to determine who goes first next turn 
} 

//Create the deck of 52 cards by setting the suit and number of each card to a nonzero integer 
void gamePlay::createDeck() { 
    for(int j = 0; j < 52; j++) 
    { 
     deck.at(j).setCardNum((j%13)+1); 
     deck.at(j).setSuit((j/13)+1); 
    } 
    random_shuffle(deck.begin(), deck.end()); 
} 

//deal out 13 cards to each player by setting the 
void gamePlay::deal(vector <spades::card> &newdeck, vector <spades::player> &newplayers){ 
    for(int i = 0; i<52; i++){ 
     newplayers.at(i/13).addCard(newdeck.at(i)); 
     newdeck.at(i).setSuit(0); 
     newdeck.at(i).setCardNum(0); 
    } 
} 

//determines if the player still has a card of the same suit in their hand as the leading card played 
bool gamePlay::containSuit(spades::card lead, spades::player players){ 
    bool suit = false; 
    for(int i = 0; i < players.getHand().size(); i++){ 
     if(lead.getSuit() == players.getHand().at(i).get 

回答

0

你必須寫默認構造函數和析構函數是這樣的:

struct display 
{ 
    display() { } 
    ~display() { } 
    //  ^^^^ 
}; 

,而不是像這樣:

struct display 
{ 
    display(); 
    ~display(); 
}; 

但是,如果你在你的頭,後者的形式和要保持這種方式,你需要定義添加到源文件:

display::display() { } 
display::~display() { } 
+0

我相信這就是我所做的。我添加了構造函數和析構函數在原始文章中定義和聲明的方式。 –

+0

@PeterBlum:這不是你在做什麼。再檢查一遍。你實際上有*多個*定義。你需要從頭文件中刪除定義(就像在我的第二個*代碼塊中,現在錯誤地說「不是這樣的」)。 –

+0

當我註釋掉'display(void){}; \t〜display(){}; // destructor 'in my display.h file,I then get compiler errors –

0

鏈接器抱怨說它無法找到對象spades::monitor和功能spades::display::drawBox(int, int, int, int)。這些定義在哪裏?請注意,在.cpp文件(或其類定義之外的任何地方)中定義成員變量/成員函數時,必須使用類名稱對其進行限定。例如:

在.H

namespace spades { 

class display { 

    static display monitor; 

    void drawBox(int, int, int, int); 
}; 

} 

在的.cpp

namespace spades { 

display display::monitor; 

void display::drawBox(int, int, int, int) { 
    //... 
} 

} 

這很難說,更沒有看到完整的代碼(的事物的連接至少定義正在抱怨)。

+0

我相信我正在那樣做......我在原始文章中添加了我的所有顯示和遊戲玩法文件,以向您展示 –

+0

@PeterBlum您有「display」的構造函數和析構函數有兩個定義(一個是.h,一個是.cpp),這是非法的。也許它會讓鏈接器感到困惑?也許'display.cpp'不會編譯,並且你正在鏈接一個陳舊的目標文件? – Angew