Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Problem w kompilacji - undefined reference to...

Ostatnio zmodyfikowano 2014-02-22 00:52
Autor Wiadomość
IFeel3
Temat założony przez niniejszego użytkownika
Problem w kompilacji - undefined reference to...
» 2014-02-21 23:52:46
Witam.
Ucząc się podstaw programowania korzystałem z e-booka "Od zera do gier kodera", gdzie po starannym (prze)pisaniu prostego programu na grę w kółko i krzyżyk natknąłem się na nieprzewidziany błąd w kompilacji:


-------------- Build: Debug in Kolko i krzyzyk (compiler: GNU GCC Compiler)---------------

mingw32-g++.exe  -o "bin\Debug\Kolko i krzyzyk.exe" obj\Debug\main.o   
obj\Debug\main.o: In function `main':
C:/Documents and Settings/.../Kolko i krzyzyk/main.cpp:8: undefined reference to `StartGry()'
C:/Documents and Settings/.../Kolko i krzyzyk/main.cpp:12: undefined reference to `RysujPlansze()'
C:/Documents and Settings/.../Kolko i krzyzyk/main.cpp:14: undefined reference to `g_StanGry'
C:/Documents and Settings/.../Kolko i krzyzyk/main.cpp:18: undefined reference to `Ruch(unsigned int)'
C:/Documents and Settings/.../Kolko i krzyzyk/main.cpp:20: undefined reference to `g_StanGry'
C:/Documents and Settings/.../Kolko i krzyzyk/main.cpp:20: undefined reference to `g_StanGry'
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 5 seconds)
6 errors, 0 warnings (0 minutes, 5 seconds)
 



Pliki zawarte w projekcie mają następującą treść:

main.cpp

C/C++
#include <iostream>
#include <conio.h>
#include "game.h"


int main()
{
    StartGry();
   
    for(;; )
    {
        RysujPlansze();
       
        if( g_StanGry == GS_MOVE )
        {
            unsigned uNumerPola;
            std::cin >> uNumerPola;
            Ruch( uNumerPola );
        }
        else if( g_StanGry == GS_WON or g_StanGry == GS_DRAW )
             break;
       
    }
   
    return 0;
    getch();
}

game.cpp

C/C++
#include <iostream>
#include <ctime>
#include "game.h"

FIELD g_aPlansza[ 3 ][ 3 ] = { { FLD_EMPTY, FLD_EMPTY, FLD_EMPTY },
    { FLD_EMPTY, FLD_EMPTY, FLD_EMPTY },
    { FLD_EMPTY, FLD_EMPTY, FLD_EMPTY } };
GAMESTATE g_StanGry = GS_NOTSTARTED;
SIGN g_AktualnyGracz;

StartGry()
{
    if( g_StanGry != GS_NOTSTARTED ) return false;
   
    srand( time( 0 ) );
    g_AktualnyGracz =( rand % 2 == 0 ? SGN_CIRCLE: SGN_CROSS );
   
    g_StanGry = GS_MOVE;
   
    return true;
}

Ruch( unsigned uNumerPola )
{
    if( g_StanGry != GS_MOVE ) return false;
   
    if( !( uNumerPola >= 1 && uNumerPola <= 9 ) ) return false;
   
    unsigned uY =( uNumerPola - 1 ) / 3;
    unsigned uX =( uNumerPola - 1 ) % 3;
   
    if( g_aPlansza[ uY ][ uX ] == FLD_EMPTY )
         g_aPlansza[ uY ][ uX ] = static_cast < FIELD >( g_AktualnyGracz );
   
   
    const LINIE[ 8 ][ 3 ][ 2 ] = { { { 0, 0 }, { 0, 1 }, { 0, 2 } }, // pozioma gorna
        { { 1, 0 }, { 1, 1 }, { 1, 2 } }, // pozioma srodkowa
        { { 2, 0 }, { 2, 1 }, { 2, 2 } }, // pozioma dolna
        { { 0, 0 }, { 1, 0 }, { 2, 0 } }, // pionowa lewa
        { { 1, 0 }, { 1, 1 }, { 1, 2 } }, // pionowa srodkowa
        { { 2, 0 }, { 2, 1 }, { 2, 2 } }, // pionowa prawa
        { { 0, 0 }, { 1, 1 }, { 2, 2 } }, // ukosna z gory na dol
        { { 0, 2 }, { 1, 1 }, { 2, 0 } } } // ukosna z dolu na gore
   
    FIELD Pole, ZgodnePole;
    unsigned uLiczbaZgodnychPol;
   
    for( int i = 0; i <= 7; i++ ) // petla sprawdzajaca zgodnosc linii, przebiega po wszystkich osmiu
    {
        Pole = ZgodnePole = FLD_EMPTY;
        uLiczbaZgodnychPol = 0; // zerujemy zmienne przed kazdym obiegiem
       
        for( int j = 0; j <= 2; j++ ) // obiegamy wszystkie 3 pola w liniach aby sprawdzic ich zgodnosc
        {
            Pole = g_aPlansza[ LINIE[ i ][ j ][ 0 ] ][ LINIE[ i ][ j ][ 1 ] ]; // przypisujemy danemu polu odpowiednie wspolrzedne
            // pionowe i poziome okreslone w stalej LINIE
            if( Pole != ZgodnePole )
            {
                ZgodnePole = Pole; // jezeli dane Pole nie zgadza sie z poprzednio okreslonym ZgodnymPolem,
                uLiczbaZgodnychPol = 1; // to zmieniamy ZgodnePole na Pole tak, aby przy kolejnym polu ponownie
                // sprawdzic mozliwa zgodnosc, oraz zmieniamy ilosc zgadzajacych sie pol na 1
            }
            else uLiczbaZgodnychPol++; // jezeli zas dane Pole zgadza sie ze ZgodnymPolem, to inkrementujemy ilosc
            // zgodnych pol
        }
       
        if( uLiczbaZgodnychPol == 3 && ZgodnePole != FLD_EMPTY ) // jezeli po obiegu danej linii ilosc zgodnych pol wynosi 3
        { // i jednoczesnie nie sa to puste pola to zmieniamy stan gry
            g_StanGry = GS_WON; // na wygrana i zwracamy prawde.
            return true;
        }
    }
   
    unsigned uLiczbaZapelnionychPol = 0; // sprawdzenie, czy wszystkie pola nie sa zapelnione przy braku wygranej,
    for( int i = 0; i <= 2; i++ )
    for( int j = 0; j <= 2; j++ )
         if( g_aPlansza[ i ][ j ] != FLD_EMPTY ) uLiczbaZapelnionychPol++;
   
    if( uLiczbaZapelnionychPol == 9 )
    {
        g_StanGry = GS_DRAW;
        return true; // jesli wszystkie pola sa zapelnione i nie ma wygranej - remis.
    }
   
    g_AktualnyGracz =( g_AktualnyGracz == SGN_CIRCLE ? SGN_CIRCLE: SGN_CROSS ) // zmiana gracza po wykonaniu ruchu
    return true;
   
}

RysujPlansze()
{
    if( g_StanGry == GS_NOTSTARTED ) return false; // sprawdzam, czy gra w ogole jest rozpoczeta
   
    system( "cls" ); // funkcja powodujaca czyszczenie konsoli
   
    std::cout << "   KOLKO I KRZYZYK   " << std::endl;
    std::cout << "---------------------" << std::endl;
    std::cout << std::endl;
   
    std::cout << "       -----" << std::endl;
    for( int i = 0; i < 3; ++i )
    {
        std::cout << "       |"; // lewa część ramki
       
        for( int j = 0; j < 3; ++j ) // wiersz
        {
            if( g_aPlansza[ i ][ j ] == FLD_EMPTY )
            // numer pola
                 std::cout << i * 3 + j + 1;
            else
                 std::cout << static_cast < char >( g_Plansza[ i ][ j ] );
           
        }
       
        std::cout << "|" << std::endl; // prawa część ramki
    }
    std::cout << "       -----" << std::endl;
    std::cout << std::endl;
   
   
    switch( g_StanGry ) // dzialania  po narysowaniu planszy w zalezosci od stanu gry
    {
    case GS_MOVE:
        std::cout << "Podaj nr pola, na ktorym " << std::endl;
    std::cout << "chcesz postawic " <<( g_AktualnyGracz == SGN_CIRCLE ? "kolko": "krzyzyk" ) << ": ";
        break;
       
    case GS_WON:
    std::cout << "Wygral gracz stawiajacy " <<( g_AktualnyGracz == SGN_CIRCLE ? "kolka": "krzyzyki" );
        break;
       
    case GS_DRAW:
        std::cout << "Remis!";
        break;
    }
   
    return true;
}

game.h

C/C++
enum SIGN { SGN_CIRCLE = 'O', SGN_CROSS = 'X' };

enum GAMESTATE { GS_NOTSTARTED, GS_MOVE, GS_WON, GS_DRAW };

enum FIELD { FLD_EMPTY, FLD_CIRCLE = SGN_CIRCLE, FLD_CROSS = SGN_CROSS };

extern GAMESTATE g_StanGry;

// PROTOTYPY FUNKCJI
// -----------------

bool StartGry();
// rozpoczecie gry

bool Ruch( unsigned );
//wykonianie ruchu

bool RysujPlansze();
//rysowanie planszy


Korzystam z CodeBlocks 12.11.
Proszę o pomoc, jestem przekonany, że kod jest napisany zgodnie z poleceniami w "podręczniku".
P-105087
SeaMonster131
» 2014-02-21 23:55:59
Brakuje Ci typów funkcji w game.cpp, zamiast
StartGry() {..
 daj
bool StartGry() {..
 itd.

Poza tym w main:
C/C++
return 0;
getch();
}
funkcja getch() nie wykona się.
P-105088
IFeel3
Temat założony przez niniejszego użytkownika
» 2014-02-22 00:03:18
Dodałem typy w game.cpp, usunałem "getch();" (dlaczego nie zadziała?) , błąd jednak pozostaje
P-105090
IFeel3
Temat założony przez niniejszego użytkownika
» 2014-02-22 00:52:19
Problem polegał na tym, że w CodeBlocks pliki game.cpp i game.h miały odznaczone linkowanie. Po zaznaczeniu (prawym na plik -> properties) i naprawieniu elementarnych błędów w kodzie program działa.
P-105091
« 1 »
  Strona 1 z 1