0

When trying to compile my code in Code::Blocks I receive a bunch of Undefined reference errors. The code is below.

Header

#ifndef BLACKJACK_GAME
#define BLACKJACK_GAME

// A game of blackjack has a deck and two hands
#include "Deck.h"
#include "BlackjackHand.h"

// Different ways the game can end.  The first states take precedence over
// over the latter states so check for the early ones first (like blackjack)!
// Note that a "natural 21" is when you are delt two cards totaling 21.
enum eGameState {
    GAME_BLACKJACK_PUSH,    // Both player and dealer have a natural 21
    GAME_DEALER_BLACKJACK,  // Dealer has a natural 21
    GAME_PLAYER_BLACKJACK,  // Player has a natural 21
    GAME_DEALER_BUST,       // The dealer has more than 21
    GAME_PLAYER_BUST,       // The player has more than 21
    GAME_DEALER_WIN,        // The dealer's score is higher than players
    GAME_PLAYER_WIN,        // The player's score is higher than dealers
    GAME_PUSH               // The scores are tied
};

class BlackjackGame
{
public:
    BlackjackGame();

    // Clear the players hands and shuffle the deck
    void newGame();

    // Play a single round of blackjack showing the output using
    // the 'PDcurses' library (for color and card suits).
    void playGameCurses();

    // Display the deck on the screen (for debugging purposes)
    void printDeckCurses();

    // Print both players hands to the screen using 'PDCurses'
    // If pShowDealerScore is true then the dealer's score is printed
    // Otherwise, the dealer's score is shown as '??'
    void printHandsCurses(bool pShowDealerScore = false) const;

    // Determine the state of the game.  Note that if you have not yet
    // played a round since you constructed this object or called newGame()
    // Then the state returned is not accurate.
    eGameState getGameState() const;

private:
    // A deck of cards for shufflying and dealing hands
    Deck mDeck;

    // The two hands for the player and the dealer
    BlackjackHand mPlayer, mDealer;

    // A helper function for prompting the player (internal use only)
    char promptPlayerCurses();

    // A helper function to quit the game (internal use only)
    void quitGameCurses();
};

#endif

CPP

#include "BlackjackGame.h"

// The library used for our text based user interface
#include <curses.h>

// Normal text color for PDCurses (defined in main)
#define NORM_TEXT   1

// Default constructor (does nothing)
BlackjackGame::BlackjackGame() {}

/* newGame() - Clear the two hands so we are ready for a new game */
void BlackjackGame::newGame()
{
    mDealer.clear();
    mPlayer.clear();
}

/* playGameCurses() - Play a single round of poker with one human player and one
 * dealer following standard Vegas rules.  Uses PDCurses for input and output to
 * the console.
 *
 * You must implement this method but you do not need to worry about curses.  Call
 * 'promptPlayerCurses() to show the hands and prompt the human player to hit, stand
 * or quit.  This method will return the key they pressed.  You can also use
 * quitGameCurses() to exit properly if the user chose to 'quit'.
 */
void BlackjackGame::playGameCurses()
{
    // TODO: Shuffle the deck and deal the cards (make sure dealer's first card is hidden).
    mDeck.shuffle();

    mPlayer.takeCard(mDeck.dealCard());
    mDealer.takeCard(mDeck.dealCard());
    mDealer.hideCard();
    mPlayer.takeCard(mDeck.dealCard());
    mDealer.takeCard(mDeck.dealCard());



    // TODO: Check for a 'natural 21' (blackjack) before playing

    if ( mDealer.hasBlackjack() || mPlayer.hasBlackjack())
        quitGameCurses();

    // TODO: Allower human player to hit, stand and quit as needed (repeat until player is done)

    int flag = 0;

    while(flag!=1)
    {
        char input = promptPlayerCurses();  // This line is an example only, a placeholder

        switch(input)
        {
            case 'h': mPlayer.takeCard(mDeck.dealCard());
                  break;
            case 's': flag =1;
                     break;

            case 'q': quitGameCurses();
                    break;
            default: break;

        }
    }
    // TODO: Play the 'dealer' hand according to vegas rules

    mDealer.showCards();

    while(vegasDealerWouldHit())
    {
        mDealer.takeCard(mDeck.dealCard());

    }

}

/* promptPlayerCurses() - Show the hands and prompt the human player to hit, stand or quit.
 * output: returns the single character entered by the player at the prompt.
 *    - 'h' means hit, 's' means stand
 *    - 'q' means you should immediatly quit (call 'quitGameCurses()')
 */
char BlackjackGame::promptPlayerCurses()
{
    // Show the hands
    printHandsCurses();

    // Hit or stand?
    attron(COLOR_PAIR(NORM_TEXT));
    mvprintw(3, 0, "Hit, stand or Quit ('h', 's', 'q'): ");
    refresh();

    // Read and return a single character
    return getch();
}

/* quitGameCurses() - End curses output and exit the program immediately */
void BlackjackGame::quitGameCurses()
{
    // End curses output, then pause and exit
    endwin();
    system("pause");
    exit(0);
}

/* printDeckCurses() - A handy function that displays the content of the game deck
 * using curses.
 *
 * This can be handy for debugging your deck and making sure it is getting properly
 * shuffled.  It is presently used for the fancy opening screen.
 */
void BlackjackGame::printDeckCurses()
{
    // Start at the upper left corner of the screen
    move(0, 0);

    // For all 52 cards
    for(int i=1; i<=52; i++)
    {
        // Get the next card and print it
        PrintableCard lCard = mDeck.dealCard();
        lCard.printCurses();

        // If we've output 13 cards then move down a row
        if(i%13 == 0)
        {
            move(2*(i/13), 0);
        }
        else
        {
            // Switch back to normal text color and output ' ' characters
            attron(COLOR_PAIR(NORM_TEXT));
            if(lCard.getFaceValue() == VALUE_TEN) printw(" ");
            else printw("  ");
        }
    }
}

/* printHandsCurses() - A function to display the current scores and hands for this game
 * using curses.
 *
 * This function is used in promptPlayerCurses() to show the hands before asking them if
 * they want to hit or stand.  Note that it alsways clears the window before drawing.
 */
void BlackjackGame::printHandsCurses(bool pShowDealerScore) const
{
    // Clear window
    erase();

    // Show dealer and player hands
    attron(COLOR_PAIR(NORM_TEXT));
    mvprintw(0, 0, "Player: %d\n", mPlayer.score());
    move(1, 0); mPlayer.printCurses();

    attron(COLOR_PAIR(NORM_TEXT));
    if(pShowDealerScore)
    {
        mvprintw(0, 50, "Dealer: %d\n", mDealer.score());
    }
    else
    {
        mvprintw(0, 50, "Dealer: ??\n");
    }
    move(1, 50); mDealer.printCurses();

    refresh();
}

/* getGameStat() - Examine the hands of both players and return the current state of
 * the game using the eGameState enum.
 *
 * You must examine the state of the game by comparing the two hands (their scores and their
 * number of cards) and return the appropriate constant from the eGameState enum.  Assume
 * that the game is over (i.e. the player and dealer have both either gone bust or decided
 * to stand).
 */
eGameState BlackjackGame::getGameState() const
{

    if(mDealer.hasBlackjack() && mPlayer.hasBlackjack())
    {
        return GAME_BLACKJACK_PUSH;
    }
    else if(mDealer.hasBlackjack())
    {
        return GAME_DEALER_BLACKJACK;
    }
    else if(mPlayer.hasBlackJack())
    {
        return GAME_PLAYER_BLACKJACK;
    }
    else if(mPlayer.score() > 21)
    {
        return GAME_PLAYER_BUST;
    }
    else if(mDealer.score() > 21)
    {
        return GAME_DEALER_BUST;
    }
    else if(mDealer.score() > mPlayer.score())
    {
        return GAME_DEALER_WIN;
    }
    else if(mDealer.score() < mPlayer.score())
    {
        return GAME_PLAYER_WIN;
    }
    else {
        return GAME_PUSH;
    }

    }
}

Main

#include <cstdlib>
#include <iostream>     // Standard input and output
#include <string>
using namespace std;

#include <curses.h>
#include "BlackjackGame.h"

// Three different types of text colors used with PDCurses
#define NORM_TEXT   1
#define WIN_TEXT    2
#define LOSE_TEXT   3

int main()

    {
        // Setup 'PDcurses'
        initscr();
        start_color();

        // Define our colors text colors (foreground, background)
        init_pair(NORM_TEXT, COLOR_WHITE, COLOR_BLACK);
        init_pair(WIN_TEXT, COLOR_YELLOW, COLOR_BLACK);
        init_pair(LOSE_TEXT, COLOR_RED, COLOR_BLACK);

        // Define our card colors (these are declared in PrintableCard.h)
        init_pair(BLACK_CARD, COLOR_BLACK, COLOR_WHITE);
        init_pair(RED_CARD, COLOR_RED, COLOR_WHITE);

        // Input from the user and a game object
        char ch = '\0';
        BlackjackGame myGame;

        // Output a 'fancy' welcome screen
        myGame.printDeckCurses();
        attron(COLOR_PAIR(WIN_TEXT));
        mvprintw(1, 13, "Welcome to Blackjack!");
        mvprintw(5, 11, "Press any key to play ...");
        refresh();

        // Wait for input (the 'press any key to begin' thing)
        ch = getch();

        // Back to normal text to start the game
        attron(COLOR_PAIR(NORM_TEXT));

        do // Loop to play a new game until the user exits
        {
            // Restart and play a game (using curses)
            myGame.newGame();

            // Play a round of blackjack (most of the magic happens here!)
            myGame.playGameCurses();

            // Print the final status of the game
            myGame.printHandsCurses(true);

            // Print a game results message (use BOLD and the appropriate text color)
            attron(A_BOLD);
            switch(myGame.getGameState())
            {
                case GAME_BLACKJACK_PUSH:
                    attron(COLOR_PAIR(WIN_TEXT));
                    mvprintw(10, 25, "BLACKJACK TIE!!");
                break;

                case GAME_DEALER_BLACKJACK:
                    attron(COLOR_PAIR(LOSE_TEXT));
                    mvprintw(10, 25, "Dealer Blackjack. You lose.");
                break;

                case GAME_PLAYER_BLACKJACK:
                    attron(COLOR_PAIR(WIN_TEXT));
                    mvprintw(10, 25, "BLACKJACK! You win!");
                break;

                case GAME_DEALER_BUST:
                    attron(COLOR_PAIR(WIN_TEXT));
                    mvprintw(10, 25, "Dealer Bust. You Win!");
                break;
                case GAME_PLAYER_BUST:
                    attron(COLOR_PAIR(LOSE_TEXT));
                    mvprintw(10, 25, "BUST. You lose.");
                break;

                case GAME_DEALER_WIN:
                    attron(COLOR_PAIR(LOSE_TEXT));
                    mvprintw(10, 25, "You lose.");
                break;

                case GAME_PLAYER_WIN:
                    attron(COLOR_PAIR(WIN_TEXT));
                    mvprintw(10, 25, "You Win!");
                break;

                case GAME_PUSH:
                    attron(COLOR_PAIR(WIN_TEXT));
                    mvprintw(10, 25, "It's a tie!");
                break;
            }

            // Turn off bold and return to normal text color
            attroff(A_BOLD);
            attron(COLOR_PAIR(NORM_TEXT));

            // Prompt user to play again
            mvprintw(20, 0, "Play again (y/n): ");
            refresh();
            ch = getch();
        } while(ch != 'n');

        // Close out 'PDCurses' and pause before exiting
        endwin();
        system("pause");
        return 0;
    }

In this program I am trying to create the game BlackJack, most of the game is in other files, but I do not receive errors in the other files. The errors come from the code inside of the Main. The errors are

undefined reference to `BlackjackGame::blackjackGame()

undefined reference to `BlackjackGame::printDeckCurses()

undefined reference to `BlackjackGame::newGame()

undefined reference to `BlackjackGame::playGameCurses()

undefined reference to `BlackjackGame::printedHandsCurses()

undefined reference to `BlackjackGame::getGameState()

With all of these errors coming from the main and these references in the header, that must be my problem, linking the two. Is that correct?

wizurd
  • 3,541
  • 3
  • 33
  • 50
Javaturtle
  • 329
  • 1
  • 2
  • 13

1 Answers1

2

This problem is telling you that you are not linking in the BlackjackGame.o object file when you are building your executable or library.

You must fix your Makefile to link in this file in order to pass the linking stage.

Edit: Seeing as how you are using Codeblocks for compilation, check these links out(as this error message means different things in different compilers):

undefined reference to function code blocks

Code::Blocks 10.05 Undefined reference to function

It looks like you need to add BlackJackGame.cpp to your project, based on the answer in link 2

Go to Project/Add files to add BlackJackGame source files to your Project, then re-build and that should work

Community
  • 1
  • 1
wizurd
  • 3,541
  • 3
  • 33
  • 50