1

所以我有2场比赛并排运行。

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

基本上发生的事情是我正在尝试集成 2 个游戏,1 个是我创建的,另一个使用相同的 display.cpp 和 display.h 文件略有改变。为了做到这一点,我创建了 2 个单独的命名空间,红桃和黑桃。我编译的所有东西都很好,但是一些 .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.o: In function `spades::gamePlay::storeBid(std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&)':
gamePlay.cpp:(.text+0x1507): undefined reference to `spades::display::captureInput()'

我在这里做错了什么?

以下是我正在使用的一些文件。让我知道是否还有我应该添加的。(我不想再膨胀这篇文章了)

游戏玩法.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);
spades::display monitor;
spades::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).getSuit())
            suit = true;
    }
    return suit;
}

//determines if the player has only spades cards left in their hand
bool gamePlay::onlySpade(spades::player play){
    for(int i = 0; i<play.getHand().size(); i++){
        if(play.getHand().at(i).getSuit()!=1)
            return false;
    }
    return true;
}

//determines if the position the player is clicking on the screen actually points to a playable card
//and then returns the position of that card based on the player's hand vector of type <card>
int gamePlay::handCheck(int xevent, int yevent, vector <spades::player> players, int trickStart){
    int i = xevent/6;
    //first check to find the card on the display
    if(i>=0 && i<players.at(0).getHand().size() && yevent>17 && yevent<23 &&
            players.at(0).getHand().at(i).getSuit() != 0 &&
            players.at(0).getHand().at(i).getCardNum() != 0)
    {
        spades::card playedCard = players.at(0).getHand().at(i);
        //check to see if leading the current round or not and if spades are "broken"
        if(trickStart==0 && !getSpadesBroken()){
            if(onlySpade(players.at(0)))
                return i;
            else if(playedCard.getSuit() != 1)
                return i;
            else
                return (-1);
        }
        if(trickStart == 0 && getSpadesBroken())
            return i;
        //if not leading, then call the containsuit method to see if your hand contains one of similar suit
        if(trickStart > 0 && containSuit(center[trickStart],players.at(0))){
            if(playedCard.getSuit()==center[trickStart].getSuit())
                return i;
        }
        if(trickStart > 0 && !containSuit(center[trickStart],players.at(0)))
            return i;
        else
            return (-1);
    }
    mvprintw(4,3,"invalid card");
    return (-1);
}

//draws the cards in the player's hand if it contains a valid card, erase the card otherwise if invalid
void gamePlay::displayHand(){
    int offset = 0;
    for(int i =0; i<players.at(0).getHand().size(); i++){
        if(players.at(0).getHand().at(i).getSuit() != 0)
            monitor.displayCard(offset, 17, players.at(0).getHand().at(i).getSuit(), players.at(0).getHand().at(i).getCardNum(), 0);
        else
            monitor.eraseBox(offset, 17, 6, 5);
        offset+=6;
    }
}
void gamePlay::displayAdd(){
    vector <string> lines;
    int count12 = 0;
    string line;
    ifstream myfile ("advertisement.txt");
    if ( myfile.is_open() )
    {
         while ( ! myfile.eof() )
         {
               getline (myfile, line);
               lines.push_back(line);
               count12++;
         }
         myfile.close();
        int random1 = rand() % 6;
        monitor.bannerBottom(lines.at(random1));
    }
    else{
          monitor.bannerBottom("Unable to open Advertisement file.");
    }

}
//determins the position of a mouse click and sends that to handcheck(), and then sends the card to the center pile array to be scored
void gamePlay::humanPlay(int trickStart){
    int xevent, yevent;
    for(;;){
        mvprintw(3,2,"Please choose a card to play.");
        int key = monitor.captureInput();
        // if a mouse click occurred
        if (key == -1) {
            xevent = monitor.getMouseEventX();
            yevent = monitor.getMouseEventY();
            int handCh = handCheck(xevent, yevent, players, trickStart);
            if(handCh != (-1)){ //if the card is valid
                spades::card played = players.at(0).getHand().at(handCh);
                players.at(0).hand.at(handCh).setCardNum(0);
                players.at(0).hand.at(handCh).setSuit(0);
                center[0]= played;
                monitor.displayCard(39, 12, center[0].getSuit(), center[0].getCardNum(), 0);
                displayHand();
                //playedCards++; //Update Global Variable---- NEED TO HAVE THIS INITIATED GLOBALLY.
                break;
            }
            else
                mvprintw(4,3,"invalid card");
        }
    }
}

//loops through a computer players hand and checks to see if the random card is playable within the rules of the game
void gamePlay::CPUplay(int trickStart, int CPU){
    bool goodCard = false;
    spades::card playedCard =players.at(CPU).getHand().at(0);
    int i;
    for(i = 0; i < players.at(CPU).getHand().size(); i++){
        if(players.at(CPU).getHand().at(i).getSuit() != 0 &&
                players.at(CPU).getHand().at(i).getCardNum() != 0){
            playedCard = players.at(CPU).getHand().at(i);
            //check to see if leading or not
            if(trickStart==CPU && !getSpadesBroken()){
                if(onlySpade(players.at(CPU)))
                    break;
                if(playedCard.getSuit()!=1)
                    break;
            }
            if(trickStart == CPU && getSpadesBroken())
                break;
            //if not leading use contains suit function
            if(trickStart != CPU && containSuit(center[trickStart], players.at(CPU)))
                if(playedCard.getSuit()==center[trickStart].getSuit())
                    break;
            if(trickStart != CPU && !containSuit(center[trickStart], players.at(CPU)))
                break;
        }
    }
    players.at(CPU).hand.at(i).setCardNum(0);
    players.at(CPU).hand.at(i).setSuit(0);
    center[CPU]= playedCard;
    if(CPU==1)
        monitor.displayCard(29, 7, center[CPU].getSuit(), center[CPU].getCardNum(), 0);
    if(CPU==2)
        monitor.displayCard(39, 2, center[CPU].getSuit(), center[CPU].getCardNum(), 0);
    if(CPU==3)
        monitor.displayCard(49, 7, center[CPU].getSuit(), center[CPU].getCardNum(), 0);
}

//scores each team with the player being teamed with CPU 2 and the other team being CPU 1 and CPU 3
void gamePlay::score(spades::player &play, spades::player &play2){
    int trickOver = play.getTricksTaken()-play.getBid(); // Calculate the difference between bid and actually taken.
    if(play.getBid() == NULL)
        trickOver = 0;
    int trickOver2 = play2.getTricksTaken()-play2.getBid(); // Calculate the difference between bid and actually taken.
    int totalBid = play.getBid()+play2.getBid();
    int totalTrick = trickOver+trickOver2;
    //Bidding Double Nil (if gets it 200 points other wise -200 points)
    if(play.getDoubleNil()){
        if(play.getTricksTaken()==0) //player did get Double Nil successfully
            play.setScore(play.getScore()+200); // add 200 points
        else
            play.setScore(play.getScore()-200);
    }
    else if(play.getBid()==0){ //Bidding Nil (if gets it 100 points other wise -100 points)
        if(play.getTricksTaken()==0) //player did get Nil successfully
            play.setScore(play.getScore()+100); //add 100 points
        else //player didnt get Nil
            play.setScore(play.getScore()-100); //take away 100 points
    }
    if(totalTrick < 0){ //player bids more than number of tricks won
        play.setScore(play.getScore()+(totalBid*(-10)));  //decrease score by 10 poitns for every overtrick
    }
    else if(totalTrick >= 0){ //player bids less then number of tricks won
        play.setSandBag(play.getSandBag() + totalTrick); //increase sandbag by 1
        play.setScore(play.getScore()+totalTrick+(10*totalBid)); //increase 10 points per trick bid on and 1 point per trick over
    }
    if(play.getSandBag()>10){ //check for sandbagging
        play.setScore(play.getScore()-100);
        play.setSandBag(play.getSandBag()-10);
    }
    play.setBid(NULL); //reset players bid to NULL
    play2.setBid(NULL); //reset players bid to NULL
    play.setTricksTaken(0);
    play2.setTricksTaken(0);
    play.setDoubleNil(false); //Player has not yet bid double NILL.
}

//loops infinitely until a mouse click or key input is detected, then sets bid accordingly
void gamePlay::storeBid(stringstream &msg){
    int xevent;
    int yevent;
    for(;;){
        mvprintw(3,2,"Click the box bid Double Nil or type out your bid now. \n  Use the keys 1-9, a for 10, b for 11, c for 12, and d for 13.");
        int key = monitor.captureInput();
        monitor.drawBox(2, 5, 3, 2, 0);
        xevent = monitor.getMouseEventX();
        yevent = monitor.getMouseEventY();
        if (key == -1)
            if((xevent>=2 && xevent<4)&&(yevent>=5 && yevent <7)){
                msg.str("");
                msg << "Your bid: double nil";
                monitor.bannerTop(msg.str());
                players.at(0).setDoubleNil(true);
                break;
            }
            else{
                msg.str("");
                msg << "Your bid is horrible. Bid again!!!!";
                monitor.bannerTop(msg.str());
            }
        if ((key-48) >= 0 && (key-48) <= 9){
            msg.str("");
            msg << "Your bid: " << (key-48);
            monitor.bannerTop(msg.str());
            players.at(0).setBid(key-48);
            break;
        }
        else if(key>=97 && key<=100){
            msg.str("");
            msg << "Your bid: " << (key-87);
            monitor.bannerTop(msg.str());
            players.at(0).setBid(key-87);
            break;
        }
        else if(key!=0 && key!=-1){
            msg.str("");
            msg << "Your bid is horrible. Bid again!!!!";
            monitor.bannerTop(msg.str());
        }
    }
    monitor.eraseBox(1, 1, 62, 16);
}

//main function that runs the entire game
void gamePlay::runGame(){
    double startTime = clock();
    stringstream messageString;
    srand(time(NULL));

    int count;
    int handStart = 0;
    int trickStart;
    while(players.at(0).getScore()<500 && players.at(1).getScore()<500)
    {
        createDeck();
        deal(deck, players); //deal out 13 cards to each player
        handSort(); // sort the human players hand
        displayHand();

        storeBid(messageString); //asks for bid

        //sets the bid randomly between 2-4 for each computer player
        players.at(1).setBid(rand()%3+2);
        players.at(2).setBid(rand()%3+2);
        players.at(3).setBid(rand()%3+2);
        //displays the current bid and scores of each team
        messageString << "  Partner: " << (players.at(2).getBid())
        << "  CPU 1: " << players.at(1).getBid()
        << "  CPU 3: " << players.at(3).getBid()
        << "    Team Score = " << players.at(0).getScore()
        << "  Enemy Score = " << players.at(1).getScore();
        monitor.bannerTop(messageString.str());
        displayAdd();
        trickStart = handStart;
        count = 0;
        setSpadesBroken(false);
        while(count<13){ // simulates the different cases where the human player plays 1st, 2nd, 3rd, last
            bool success = true;
            switch (trickStart)
            {
            case 0: humanPlay(trickStart);
            CPUplay(trickStart,1);
            CPUplay(trickStart,2);
            CPUplay(trickStart,3);
            break;
            case 3: CPUplay(trickStart,3);
            humanPlay(trickStart);
            CPUplay(trickStart,1);
            CPUplay(trickStart,2);
            break;
            case 2: CPUplay(trickStart,2);
            CPUplay(trickStart,3);
            humanPlay(trickStart);
            CPUplay(trickStart,1);
            break;
            case 1: CPUplay(trickStart,1);
            CPUplay(trickStart,2);
            CPUplay(trickStart,3);
            humanPlay(trickStart);
            break;
            default: mvprintw(3,2,"!!!!we have a problem!!!!");
            success = false;
            break;
            }
            monitor.eraseBox(3, 2, 20, 2);

            for(;;){//pause to wait for an acknowledgment mouse click
                int key = monitor.captureInput();
                monitor.eraseBox(3, 2, 30, 4);
                mvprintw(3,2,"click anywhere to continue");
                if(key == -1){
                    break;
                }
            }
            //if no errors appear, display the tricks taken
            if(success){
                monitor.eraseBox(1, 1, 62, 16);
                trickStart = compareCenter(trickStart);
                messageString.str("");
                messageString << "Your Tricks= " << players.at(0).getTricksTaken()
                << "   Partner= " << players.at(2).getTricksTaken()
                << "   CPU 1= " << players.at(1).getTricksTaken()
                << "   CPU 3= " << players.at(3).getTricksTaken();
                displayAdd();
                monitor.bannerAboveBottom(messageString.str());
                count++;
            }
        }

        //score the round and tally up for each team
        for(int n =0; n<2;n++)
            score(players.at(n),players.at(n+2));
        messageString.str("");
        monitor.bannerTop(messageString.str());
        messageString << "Your Tricks = " << players.at(0).getTricksTaken()
        << "   Partner = " << players.at(2).getTricksTaken()
        << "   CPU 1 = " << players.at(1).getTricksTaken()
        << "   CPU 3 = " << players.at(3).getTricksTaken();
        handStart = (handStart +1) % 4;
    }
    double endTime = clock();

}


}

游戏玩法.h

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

#ifndef gamePlay_H
#define gamePlay_H
namespace spades {
using namespace std;

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

播放器.h

#include <iostream> // Stream declarations
#include <vector> //Vectors used to store deck and players hands
#include <string> //String declarations
#include <algorithm> //Shuffle Method
#include "card.h"

#ifndef PLAYER_H
#define PLAYER_H
namespace spades {
using namespace std;

class player {


    int score; //total score
    int bid; //bid for that round
    int tricksTaken; //score for thast round
    int sandBag; //the number of points you win, more than what you bid, every 10th bag = -100
    bool doubleNil;
    //vector <card> hand;

public:
    player();
    vector <card> hand;

    int getSandBag(){return sandBag;}
    bool getDoubleNil() {return doubleNil;}
    int getScore() {return score;}
    int getBid() {return bid;}
    int getTricksTaken() {return tricksTaken;}
    vector<card> getHand() {return hand;}

    void setSandBag(int i) {sandBag = i;}
    void setBid(int i) {bid = i;}
    void setTricksTaken(int i) {tricksTaken=i;}
    void setScore(int i) {score = i;}
    void setDoubleNil(bool i) {doubleNil = i;}

    //add card to end of vector
    void addCard(card b);
    void removeCard(card a);

};
}
#endif

播放器.cpp

#include <iostream> // Stream declarations
#include <vector> //Vectors used to store deck and players hands
#include <string> //String declarations
#include <algorithm> //Shuffle Method
#include <sys/ioctl.h>
#include <cstdio>
#include <unistd.h>
#include <locale.h>
#include <ncursesw/ncurses.h>
#include "player.h"
namespace spades {
using namespace std;


player::player() {
    score =0; //total score
    bid = NULL; //bid for that round
    tricksTaken = 0; //score for thast round
    sandBag = 0; //the number of points you win, more than what you bid, every 10th bag = -100
    doubleNil = false;
    for(int i=0; i<13; i++)
        hand.push_back(card());
}

void player::addCard(spades::card b){
    for (int i=0; i<hand.size(); i++){
        //compare card being played to the ones in your hand to search and determine which one to erase
        if((hand.at(i).getCardNum() == 0) &&
            (hand.at(i).getSuit() == 0))
        {
            hand.at(i).setCardNum(b.getCardNum());
            hand.at(i).setSuit(b.getSuit());
            return;
        }
    }
}

void player::removeCard(spades::card a) {
    for (int i=0; i<hand.size(); i++){
        //compare card being played to the ones in your hand to search and determine which one to erase
        if((hand.at(i).getCardNum() == a.getCardNum()) &&
            (hand.at(i).getSuit() == a.getSuit()))
        {
            hand.at(i).setCardNum(0);
            hand.at(i).setSuit(0);
            return;
        }
    }
}
}
4

1 回答 1

1

你的链接线是什么样子的?看起来当您链接时,您缺少 spades.o?

如果不是这样,请使用 nm 命令查看 spades.o 提供的符号 - 总是有可能您打错了命名空间名称或其他内容:

nm -C spades.o | grep 'display::.*display'

(-C 选项应该将 nm 置于 C++/解组模式 - 如果它不适合您的 nm,请在 grep 之前向管道链添加“c++filt”或“dem”步骤)。

于 2012-11-28T20:12:58.693 回答