所以我有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;
}
}
}
}