ArmielNailo Temat założony przez niniejszego użytkownika |
main.cpp:(.text+0xe): undefined reference to `StartGry()',RysujPlansze(),Ruch(unsigned int),g_StanGry » 2016-06-12 23:31:24 http://xion.org.pl/productions/texts/coding/megatutorial/ na podstawie tego tutorialu robiłem konsolową grę w kółko i krzyżyk. I na końcowym etapie wyszedł mi ten problem. wiem że jest związany z linkowaniem (prawdopodobnie) naszukałem się już parę ładnych godzin na google i nie widzę rozwiązania. Przeczytałem temat związany z dzieleniem na moduły na tym forum i dalej nic. Po prostu nie widzę gdzie jest błąd. Używam Code Blocka wersji 16.01. Kodzik do przejrzenia // main.cpp #include <iostream> #include <conio.h> #include "game.h" using namespace std;
int main() { StartGry(); for(;; ) { RysujPlansze(); if( g_StanGry == GS_MOVE ) { unsigned uNumerPola; cin >> uNumerPola; Ruch( uNumerPola ); } else if( g_StanGry == GS_WON || g_StanGry == GS_DRAW ) break; } getch(); return 0; }
. //game.cpp #include <iostream> #include <conio.h> #include <ctime> #include <cstdlib> #include "game.h" using namespace std;
public: 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; int rand(); bool StartGry() { if( g_StanGry != GS_NOTSTARTED ) return false; srand( static_cast < unsigned >( time( NULL ) ) ); g_AktualnyGracz =( rand() % 2 == 0 ? SGN_CIRCLE : SGN_CROSS ); g_StanGry = GS_MOVE; return true; } bool 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 ) else return false; g_aPlansza[ uY ][ uX ] = static_cast < FIELD >( g_AktualnyGracz ); const LINIE[][ 3 ][ 2 ] = { { { 0, 0 }, { 0, 1 }, { 0, 2 } }, { { 1, 0 }, { 1, 1 }, { 1, 2 } }, { { 2, 0 }, { 2, 1 }, { 2, 2 } }, { { 0, 0 }, { 1, 0 }, { 2, 0 } }, { { 0, 1 }, { 1, 1 }, { 2, 1 } }, { { 0, 2 }, { 1, 2 }, { 2, 2 } }, { { 0, 0 }, { 1, 1 }, { 2, 2 } }, { { 2, 0 }, { 1, 1 }, { 0, 2 } } }; FIELD Pole, ZgodnePole; unsigned uLiczbaZgodnychPol; for( int i = 0; i < 8; ++i ) { Pole = ZgodnePole = FLD_EMPTY; uLiczbaZgodnychPol = 0; for( int j = 0; j < 3; ++j ) { Pole = g_aPlansza[ LINIE[ i ][ j ][ 0 ] ][ LINIE[ i ][ j ][ 1 ] ]; if( Pole != ZgodnePole ) { ZgodnePole = Pole; uLiczbaZgodnychPol = 1; } else ++uLiczbaZgodnychPol; } if( uLiczbaZgodnychPol == 3 && ZgodnePole != FLD_EMPTY ) { g_StanGry = GS_WON; return true; } unsigned uLiczbaZapelnionychPol = 0; for( int i = 0; i < 3; ++i ) for( int j = 0; j < 3; ++j ) if( g_aPlansza[ i ][ j ] != FLD_EMPTY ) ++uLiczbaZapelnionychPol; if( uLiczbaZapelnionychPol == 3 * 3 ) { g_StanGry = GS_DRAW; return true; } g_AktualnyGracz =( g_AktualnyGracz == SGN_CIRCLE ? SGN_CROSS: SGN_CIRCLE ); return true; } } bool RysujPlansze() { if( g_StanGry == GS_NOTSTARTED ) return false; system( "cls" ); 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 ) { cout << " |"; for( int j = 0; j < 3; ++j ) { if( g_aPlansza[ i ][ j ] == FLD_EMPTY ) cout << i * 3 + j * 3 + 1; else cout << static_cast < char >( g_aPlansza[ i ][ j ] ); } cout << "|" << endl; cout << end; switch( g_StanGry ) { case GS_MOVE: std::cout << "Podaj numer pola, w ktorym" << std::endl; std::cout << "chcesz postawic "; std::cout <<( g_AktualnyGracz == SGN_CIRCLE ? "kolko": "krzyzyk" ) << ": "; break; case GS_WON: std::cout << "Wygral gracz stawiajacy "; std::cout <<( g_AktualnyGracz == SGN_CIRCLE ? "kolka": "krzyzyki" ) << "!"; break; case GS_DRAW: std::cout << "Remis!"; break; } return true; } }
}
. // game.h #ifndef game_h #define game_h
enum SIGN { SGN_CIRCLE = 'O', SGN_CROSS = 'X' }; enum FIELD { FLD_EMPTY, FLD_CIRCLE = SGN_CIRCLE, FLD_CROSS = SGN_CROSS }; enum GAMESTATE { GS_NOTSTARTED, GS_MOVE, GS_WON, GS_DRAW }; extern GAMESTATE g_StanGry;
bool StartGry();
bool Ruch( unsigned );
bool RysujPlansze();
#endif
. [/i] |
|
carlosmay |
» 2016-06-13 06:29:20 int rand(); StartGry() { if( g_StanGry != GS_NOTSTARTED ) return false; srand( static_cast < unsigned >( time( NULL ) ) ); g_AktualnyGracz =( rand() % 2 == 0 ? SGN_CIRCLE : SGN_CROSS );
|
To są pierwsze z brzegu błędy. Reszty nie czytałem, bo ten post jest koszmarny. |
|
ArmielNailo Temat założony przez niniejszego użytkownika |
» 2016-06-13 11:51:26 Poprawiłem wpis.. Teraz w odpowiedzi na twoje pytania: 1. int rand() jest to funkcja losująca liczbę , jest ona użyta później kompilator mi krzyczał że muszę podać jej typ 2. Uciekła mi deklaracja typu w pliku game.cpp ale była w pliku game.h który jest plikiem nagłówkowym, w każdym razie to nie poprawiło sytuacji i kompilator dalej ze mną walczy. 3.To wyrażenie warunkowe losuje pomiędzy dwoma instancjami typu wyliczeniowego enum nazwanej SIGN, i przypisuje wartość wylosowanej do zmiennej g_AktualnyGracz. Losuje pomiędzy 0 a 1 jeżeli warunek pierwszy czyli 0 zostanie spełniony to przypisze wartość SGN_Circle a jeżeli nie zostanie on spełniony to przypisze wartość SGN_Cross
Ułożyłem całość kodu w jednym pliku main.cpp i po małych zmianach całość działa. Więc nie ma problemu z samą kompilacją kodu. Po prostu jest problem w tym że chciałbym żeby były trzy pliki main.cpp, game.cpp i game.h i kiedy wszystko rozdzielam tak jak jest w tutorialu to wyświetlają mi się błędy "main.cpp:(.text+0xe): undefined reference to `StartGry()',RysujPlansze(),Ruch(unsigned int),g_StanGry ". Więc ewidentnie jest to problem z plikiem nagłówka game.h który nie działa jak powinien. Tak jakby main jeżeli dobrze rozumiem nie widział moich funkcji StartGry() RysujPlansze itd... |
|
pekfos |
» 2016-06-13 12:48:18 Wszystkie pliki są dołączone do projektu? #include "game.h" using namespace std;
public: FIELD g_aPlansza[ 3 ][ 3 ] = { { FLD_EMPTY, FLD_EMPTY, FLD_EMPTY }, |
Co to za public? |
|
ArmielNailo Temat założony przez niniejszego użytkownika |
» 2016-06-13 12:58:57 Ten public : to eksperyment czy coś zmieni ale chyba jest nie potrzebny. pliki w projekcie wyglądają następująco: Sourcers : main.cpp game.cpp Headers : game.h Jeżeli chodzi o plik game.h to został includowany i w pliku game.cpp i pliku main.cpp |
|
pekfos |
» 2016-06-13 13:03:11 Ten public to błąd składniowy. Skoro 'chyba nie jest potrzebny' to znaczy, że nie kompilujesz projektu. |
|
ArmielNailo Temat założony przez niniejszego użytkownika |
» 2016-06-13 13:29:03 Ten public został usunięty on nic nie zmienił. Chciałbym po prostu dowiedzieć się czy robię coś źle w kwestii nagłówka game.h i pliku game.cpp. Całość programu kiedy wrzuce do main.cpp kompiluje się i nie ma żadnych problemów. Może inaczej // plik main.cpp który działa samoistnie i kompiluje się wszystko działa poprawnie. #include <iostream> #include <conio.h> #include <ctime> #include <cstdlib>
using namespace std; enum SIGN { SGN_CIRCLE = 'O', SGN_CROSS = 'X' }; enum FIELD { FLD_EMPTY, FLD_CIRCLE = SGN_CIRCLE, FLD_CROSS = SGN_CROSS }; enum GAMESTATE { GS_NOTSTARTED, GS_MOVE, GS_WON, GS_DRAW }; extern GAMESTATE g_StanGry; 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; int rand(); bool StartGry() { if( g_StanGry != GS_NOTSTARTED ) return false; srand( static_cast < unsigned >( time( NULL ) ) ); g_AktualnyGracz =( rand() % 2 == 0 ? SGN_CIRCLE : SGN_CROSS ); g_StanGry = GS_MOVE; return true; } bool 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 ); else return false; const int LINIE[ 8 ][ 3 ][ 2 ] = { { { 0, 0 }, { 0, 1 }, { 0, 2 } }, { { 1, 0 }, { 1, 1 }, { 1, 2 } }, { { 2, 0 }, { 2, 1 }, { 2, 2 } }, { { 0, 0 }, { 1, 0 }, { 2, 0 } }, { { 0, 1 }, { 1, 1 }, { 2, 1 } }, { { 0, 2 }, { 1, 2 }, { 2, 2 } }, { { 0, 0 }, { 1, 1 }, { 2, 2 } }, { { 2, 0 }, { 1, 1 }, { 0, 2 } } }; FIELD Pole, ZgodnePole; unsigned uLiczbaZgodnychPol; for( int i = 0; i < 8; ++i ) { Pole = ZgodnePole = FLD_EMPTY; uLiczbaZgodnychPol = 0; for( int j = 0; j < 3; ++j ) { Pole = g_aPlansza[ LINIE[ i ][ j ][ 0 ] ][ LINIE[ i ][ j ][ 1 ] ]; if( Pole != ZgodnePole ) { ZgodnePole = Pole; uLiczbaZgodnychPol = 1; } else ++uLiczbaZgodnychPol; } if( uLiczbaZgodnychPol == 3 && ZgodnePole != FLD_EMPTY ) { g_StanGry = GS_WON; return true; } } unsigned uLiczbaZapelnionychPol = 0; for( int i = 0; i < 3; ++i ) for( int j = 0; j < 3; ++j ) if( g_aPlansza[ i ][ j ] != FLD_EMPTY ) ++uLiczbaZapelnionychPol; if( uLiczbaZapelnionychPol == 3 * 3 ) { g_StanGry = GS_DRAW; return true; } g_AktualnyGracz =( g_AktualnyGracz == SGN_CIRCLE ? SGN_CROSS: SGN_CIRCLE ); return true; }
bool RysujPlansze() { if( g_StanGry == GS_NOTSTARTED ) return false; system( "cls" ); 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 ) { cout << " |"; for( int j = 0; j < 3; ++j ) { if( g_aPlansza[ i ][ j ] == FLD_EMPTY ) cout << i * 3 + j + 1; else cout << static_cast < char >( g_aPlansza[ i ][ j ] ); } cout << "|" << endl; } cout << " -----" << endl; cout << endl; switch( g_StanGry ) { case GS_MOVE: std::cout << "Podaj numer pola, w ktorym" << std::endl; std::cout << "chcesz postawic "; std::cout <<( g_AktualnyGracz == SGN_CIRCLE ? "kolko": "krzyzyk" ) << ": "; break; case GS_WON: std::cout << "Wygral gracz stawiajacy "; std::cout <<( g_AktualnyGracz == SGN_CIRCLE ? "kolka": "krzyzyki" ) << "!"; break; case GS_DRAW: std::cout << "Remis!"; break; } return true; }
int main() { StartGry(); for(;; ) { RysujPlansze(); if( g_StanGry == GS_MOVE ) { unsigned uNumerPola; cin >> uNumerPola; Ruch( uNumerPola ); } else if( g_StanGry == GS_WON || g_StanGry == GS_DRAW ) break; } getch(); return 0; }
A teraz pliki poglądowe , czyli tak jak bym chciał żeby to wyglądało
#include <iostream> #include <conio.h> #include "game.h" using namespace std;
int main() { StartGry(); for(;; ) { RysujPlansze(); if( g_StanGry == GS_MOVE ) { unsigned uNumerPola; cin >> uNumerPola; Ruch( uNumerPola ); } else if( g_StanGry == GS_WON || g_StanGry == GS_DRAW ) break; } getch(); return 1; }
//game.cpp #include <iostream> #include <conio.h> #include <ctime> #include <cstdlib> #include "game.h" using namespace std;
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; int rand(); bool StartGry() { if( g_StanGry != GS_NOTSTARTED ) return false; srand( static_cast < unsigned >( time( NULL ) ) ); g_AktualnyGracz =( rand() % 2 == 0 ? SGN_CIRCLE : SGN_CROSS ); g_StanGry = GS_MOVE; return true; } bool 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 ); else return false; const int LINIE[ 8 ][ 3 ][ 2 ] = { { { 0, 0 }, { 0, 1 }, { 0, 2 } }, { { 1, 0 }, { 1, 1 }, { 1, 2 } }, { { 2, 0 }, { 2, 1 }, { 2, 2 } }, { { 0, 0 }, { 1, 0 }, { 2, 0 } }, { { 0, 1 }, { 1, 1 }, { 2, 1 } }, { { 0, 2 }, { 1, 2 }, { 2, 2 } }, { { 0, 0 }, { 1, 1 }, { 2, 2 } }, { { 2, 0 }, { 1, 1 }, { 0, 2 } } }; FIELD Pole, ZgodnePole; unsigned uLiczbaZgodnychPol; for( int i = 0; i < 8; ++i ) { Pole = ZgodnePole = FLD_EMPTY; uLiczbaZgodnychPol = 0; for( int j = 0; j < 3; ++j ) { Pole = g_aPlansza[ LINIE[ i ][ j ][ 0 ] ][ LINIE[ i ][ j ][ 1 ] ]; if( Pole != ZgodnePole ) { ZgodnePole = Pole; uLiczbaZgodnychPol = 1; } else ++uLiczbaZgodnychPol; } if( uLiczbaZgodnychPol == 3 && ZgodnePole != FLD_EMPTY ) { g_StanGry = GS_WON; return true; } } unsigned uLiczbaZapelnionychPol = 0; for( int i = 0; i < 3; ++i ) for( int j = 0; j < 3; ++j ) if( g_aPlansza[ i ][ j ] != FLD_EMPTY ) ++uLiczbaZapelnionychPol; if( uLiczbaZapelnionychPol == 3 * 3 ) { g_StanGry = GS_DRAW; return true; } g_AktualnyGracz =( g_AktualnyGracz == SGN_CIRCLE ? SGN_CROSS: SGN_CIRCLE ); return true; }
bool RysujPlansze() { if( g_StanGry == GS_NOTSTARTED ) return false; system( "cls" ); 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 ) { cout << " |"; for( int j = 0; j < 3; ++j ) { if( g_aPlansza[ i ][ j ] == FLD_EMPTY ) cout << i * 3 + j + 1; else cout << static_cast < char >( g_aPlansza[ i ][ j ] ); } cout << "|" << endl; } cout << " -----" << endl; cout << endl; switch( g_StanGry ) { case GS_MOVE: std::cout << "Podaj numer pola, w ktorym" << std::endl; std::cout << "chcesz postawic "; std::cout <<( g_AktualnyGracz == SGN_CIRCLE ? "kolko": "krzyzyk" ) << ": "; break; case GS_WON: std::cout << "Wygral gracz stawiajacy "; std::cout <<( g_AktualnyGracz == SGN_CIRCLE ? "kolka": "krzyzyki" ) << "!"; break; case GS_DRAW: std::cout << "Remis!"; break; } return true; } }
}
//i nagłówek game.h #ifndef game_h #define game_h
enum SIGN { SGN_CIRCLE = 'O', SGN_CROSS = 'X' }; enum FIELD { FLD_EMPTY, FLD_CIRCLE = SGN_CIRCLE, FLD_CROSS = SGN_CROSS }; enum GAMESTATE { GS_NOTSTARTED, GS_MOVE, GS_WON, GS_DRAW }; extern GAMESTATE g_StanGry;
bool StartGry();
bool Ruch( unsigned );
bool RysujPlansze();
#endif
|
|
darko202 |
» 2016-06-13 13:55:05 1. Nie napisałeś jakie błędy Ci się pojawiają. a na tworzenie projektu i przenoszenie kodu jestem dziś za leniwy :-)
2. Sprawdź zmienne.
jeśli zmienną np. GAMESTATE g_StanGry = GS_NOTSTARTED; deklarujesz w pliku "game.cpp" a nie game.h
to jest ona widoczna czy nie ? ( w "main.cpp" ) 3. jaki cel ma taki podział ?
jeśli popatrzysz na to obiektowo, to nawet nie programując obiektowo oddzielnie powinieneś umieścić elementy odpowiedzialne za grę (plansza, logika, ..), a oddzielnie za gracza
|
|
« 1 » 2 |