XardassLord Temat założony przez niniejszego użytkownika |
[C++] Problem przy tworzeniu mapy w grze Snake » 2013-05-20 23:10:32 Witam, Zaznaczę na początku iż dopiero jakoś od ponad miesiąca przyłożyłem się do nauki c++. Wcześniej na pierwszym roku studiów uczyliśmy się C, potem javy, więc nie jestem w tym temacie aż taki zielony. Programowanie mnie interesuje, dlatego chcę rozwijać swoje zainteresowania i kształcić się w tym kierunku. Zakupiłem do tego celu książkę Jerzego Grębosza - Symfonia C++ standard. Uczę się z niej na bieżąco, razem z przykładami i próbuję pisać swoje własne programy, które przyjdą mi do głowy. Jestem osobą, która lubi uczyć się na własnych błędach, lecz problemu z którym próbuję się uporać nie mogę rozwikłać. Domyślam się, że przyczyna tego jest banalna, lecz na dzień dzisiejszy nie mogę pojąć dlaczego... Dlatego mam nadzieję, że mi pomożecie i wyjaśnicie dlaczego to jest źle. Problem, a dokładniej rzecz mówiąc, bardziej taka ciekawostka, której nie mogę zrozumieć pojawia się podczas rysowania mapy (a dokładniej głowy węża). Ale o tym bliżej za chwilę. Moja mapa jest tablicą dwuwymiarową obiektów typu char. Posiadam dwie funkcje, jedna która rysuje mapę (tj. obramowanie i ustawia każdy z elementów tej tablicy jako znak ASCII o kodzie 255 (czyli spacja). Oraz druga, która powinna rysować głowę węża o podanych wartościach tej tablicy. Lecz niestety nie rysuje. Natomiast, gdy rysowanie węża uwzględnie w funkcji, która rysuje mapę to głowa węża zostaje na tej mapie narysowana. Dlaczego tak się dzieje? I dlaczego głowa węża nie chce się narysować za pomocą oddzielnej funkcji? Byłbym niezmiernie wdzięczny, gdyby ktoś mógł mi tę sytuację wytłumaczyć :) Oto kod programu: #include <iostream> #include <conio.h> #include <cstdlib>
using namespace std;
void rysuj_mape( char mapa[ 20 ][ 60 ] ); void wstaw_weza( char mapa[ 20 ][ 60 ] );
int main() { char mapa[ 20 ][ 60 ]; rysuj_mape( mapa ); wstaw_weza( mapa ); getch(); return 0; }
void rysuj_mape( char mapa[ 20 ][ 60 ] ) { cout << " ------------------------------------------------------------" << endl; for( int i = 0; i < 20; i++ ) { cout << "|"; for( int j = 0; j < 60; j++ ) { mapa[ i ][ j ] = 255; cout << mapa[ i ][ j ]; } cout << "|"; cout << endl; } cout << " ------------------------------------------------------------" << endl; }
void wstaw_weza( char mapa[ 20 ][ 60 ] ) { mapa[ 10 ][ 30 ] = 'O'; }
|
|
f651144 |
» 2013-05-21 08:59:46 1. Nie wiem z dlaczego spacja u Ciebie to 255. Odsyłam do: Wikipedia, artykuł o ASCII. Spacja to 32 (0x20), więc Twój kod powinie wyglądać mniej więcej tak: for( int j = 0; j < 60; j++ ) { mapa[ i ][ j ] =( char ) 32; cout << mapa[ i ][ j ]; } 2. Twój problem wynika z tego, że NAJPIERW rysujesz mapę, a PÓŹNIEJ wstawiasz węża. Jeśli tylko zmienisz kolejność będzie problem z rysowaniem. Możesz dodać funkcje czyszczącą tablice i lekko zmodyfikować funkcje rysuj_mape. Będzie to wyglądało jakoś tak: #include <iostream> #include <conio.h> #include <cstdlib>
using namespace std;
void zeruj_mape( char mapa[ 20 ][ 60 ] ); void wstaw_weza( char mapa[ 20 ][ 60 ] ); void rysuj_mape( char mapa[ 20 ][ 60 ] );
int main() { char mapa[ 20 ][ 60 ]; zeruj_mape( mapa ); wstaw_weza( mapa ); rysuj_mape( mapa ); getch(); return 0; }
void zeruj_mape( char mapa[ 20 ][ 60 ] ) { for( int i = 0; i < 20; i++ ) for( int j = 0; j < 60; j++ ) mapa[ i ][ j ] =( char ) 0; }
void rysuj_mape( char mapa[ 20 ][ 60 ] ) { cout << " ------------------------------------------------------------" << endl; for( int i = 0; i < 20; i++ ) { cout << "|"; for( int j = 0; j < 60; j++ ) { if( mapa[ i ][ j ] != 'O' ) mapa[ i ][ j ] =( char ) 32; cout << mapa[ i ][ j ]; } cout << "|"; cout << endl; } cout << " ------------------------------------------------------------" << endl; }
void wstaw_weza( char mapa[ 20 ][ 60 ] ) { mapa[ 10 ][ 30 ] = 'O'; } |
|
XardassLord Temat założony przez niniejszego użytkownika |
» 2013-05-21 11:24:10 Rzeczywiście, można to rozwiązać w taki sposób. Dzięki bardzo za odpowiedź. Lecz teraz kwestia taka, gdybym chciał dodać jabłko do mapy ( odpowiadałaby za to funkcja losująca dwie liczby, które wstawiłbym jako elementy tablicy, czyli przykładowo mapa[y][x]) to sytuacja wyglądałaby podobnie jak ze wstawieniem węża do mapy... Po prostu po narysowaniu mapy, nie mógłbym tak jak to było wcześniej z głową węża - narysować jej. A przecież funkcja losująca mapę będzie co jakiś czas musiała losować te liczby i wstawiać w dane miejsce w tablicy jabłko. Czy w takim razie w funkcji tej będę musiał jeszcze raz uwzględnić rysowanie mapy i tam wtedy podać, że pierw zeruje tablice, potem dodaje węża i jabłko i następnie całą resztę tablicy wypełnia spacjami? EDIT: Okej ogarnąłem troche ten kod i już wiem o co chodzi w tym wszystkim. Zmodyfikowałem nieco funkcję rysuj_mape, uwzględniając w niej pozycję węża. Napisałem również pozostałe funkcje, tj. poruszanie węża, oraz sprawdzanie czy wąż nie uderzył w ścianę (czy nie jest przekroczony zakres tablicy). Poniżej przesyłam kod i chciałbym, abyście mi podpowiedzieli w jaki sposób mógłbym ten kod zoptymalizować, by był nieco krótszy i prostrzy. Jestem w tej dziedzinie słaby, także chętnie wysłucham wszystkich Waszych porad :) Wiem też, że używałem tam często polecenia na czyszczenie ekranu (system("cls")) i wiem też, że na pewno można co zrobić inaczej, lepiej. #include <iostream> #include <conio.h> #include <cstdlib>
using namespace std;
void zeruj_mape( char mapa[ 20 ][ 60 ] ); void rysuj_mape( char mapa[ 20 ][ 60 ] ); void wstaw_weza( char mapa[ 20 ][ 60 ], int & x, int & y ); void ruch( char mapa[ 20 ][ 60 ], int & x, int & y ); bool koniec( char mapa[ 20 ][ 60 ], int & x, int & y );
int main() { char mapa[ 20 ][ 60 ]; int x = 30; int y = 10; do { system( "cls" ); zeruj_mape( mapa ); wstaw_weza( mapa, x, y ); rysuj_mape( mapa ); ruch( mapa, x, y ); koniec( mapa, x, y ); } while( !koniec( mapa, x, y ) ); getch(); return 0; }
void zeruj_mape( char mapa[ 20 ][ 60 ] ) { for( int i = 0; i < 20; i++ ) for( int j = 0; j < 60; j++ ) mapa[ i ][ j ] = 0; }
void rysuj_mape( char mapa[ 20 ][ 60 ] ) { cout << " ------------------------------------------------------------" << endl; for( int i = 0; i < 20; i++ ) { cout << "|"; for( int j = 0; j < 60; j++ ) { if( mapa[ i ][ j ] != 'O' ) mapa[ i ][ j ] = 32; cout << mapa[ i ][ j ]; } cout << "|"; cout << endl; } cout << " ------------------------------------------------------------" << endl; }
void wstaw_weza( char mapa[ 20 ][ 60 ], int & x, int & y ) { mapa[ y ][ x ] = 'O'; }
void ruch( char mapa[ 20 ][ 60 ], int & x, int & y ) { char ruch = getch(); if( ruch == 'w' ) { y--; system( "cls" ); zeruj_mape( mapa ); wstaw_weza( mapa, x, y ); rysuj_mape( mapa ); } if( ruch == 's' ) { y++; system( "cls" ); zeruj_mape( mapa ); wstaw_weza( mapa, x, y ); rysuj_mape( mapa ); } if( ruch == 'a' ) { x--; system( "cls" ); zeruj_mape( mapa ); wstaw_weza( mapa, x, y ); rysuj_mape( mapa ); } if( ruch == 'd' ) { x++; system( "cls" ); zeruj_mape( mapa ); wstaw_weza( mapa, x, y ); rysuj_mape( mapa ); } }
bool koniec( char mapa[ 20 ][ 60 ], int & x, int & y ) { bool test = false; if( x < 0 || x > 59 ) { test = true; system( "cls" ); cout << "\n\n KONIEC GRY!"; return test; } if( y < 0 || y > 19 ) { test = true; system( "cls" ); cout << "\n\n KONIEC GRY!"; return test; } return test; }
|
|
pekfos |
» 2013-05-21 19:02:25 1. Nie wiem z dlaczego spacja u Ciebie to 255. |
A u Ciebie nie (o ile masz extended ASCII)? |
|
XardassLord Temat założony przez niniejszego użytkownika |
» 2013-05-21 22:05:33 Program udało mi się skrócić do takiej postaci jak w kodzie poniżej. Dodałem dodatkowo funkcję losującą i wstawiającą na mapę jabłka :) #include <iostream> #include <conio.h> #include <cstdlib> #include <ctime>
using namespace std;
void zeruj_mape( char mapa[ 20 ][ 60 ] ); void rysuj_mape( char mapa[ 20 ][ 60 ] ); void wstaw_weza( char mapa[ 20 ][ 60 ], int & x, int & y ); void ruch( char mapa[ 20 ][ 60 ], int & x, int & y ); bool koniec( char mapa[ 20 ][ 60 ], int & x, int & y ); void losuj_jablko( char mapa[ 20 ][ 60 ], int & x, int & y, int & jx, int & jy );
int main() { srand( time( NULL ) ); char mapa[ 20 ][ 60 ]; int x = 30; int y = 10; int jx = rand() % 59; int jy = rand() % 19; do { system( "cls" ); zeruj_mape( mapa ); wstaw_weza( mapa, x, y ); losuj_jablko( mapa, x, y, jx, jy ); rysuj_mape( mapa ); ruch( mapa, x, y ); koniec( mapa, x, y ); } while( !koniec( mapa, x, y ) ); getch(); return 0; }
void zeruj_mape( char mapa[ 20 ][ 60 ] ) { for( int i = 0; i < 20; i++ ) for( int j = 0; j < 60; j++ ) mapa[ i ][ j ] = 0; }
void rysuj_mape( char mapa[ 20 ][ 60 ] ) { cout << " ------------------------------------------------------------" << endl; for( int i = 0; i < 20; i++ ) { cout << "|"; for( int j = 0; j < 60; j++ ) { if( mapa[ i ][ j ] == 0 ) mapa[ i ][ j ] = 32; cout << mapa[ i ][ j ]; } cout << "|"; cout << endl; } cout << " ------------------------------------------------------------" << endl; }
void wstaw_weza( char mapa[ 20 ][ 60 ], int & x, int & y ) { mapa[ y ][ x ] = 'O'; }
void ruch( char mapa[ 20 ][ 60 ], int & x, int & y ) { char ruch = getch(); if( ruch == 'w' ) y--; if( ruch == 's' ) y++; if( ruch == 'a' ) x--; if( ruch == 'd' ) x++; }
bool koniec( char mapa[ 20 ][ 60 ], int & x, int & y ) { bool test = false; if( x < 0 || x > 59 ) { test = true; system( "cls" ); cout << "\n\n KONIEC GRY!"; return test; } if( y < 0 || y > 19 ) { test = true; system( "cls" ); cout << "\n\n KONIEC GRY!"; return test; } return test; }
void losuj_jablko( char mapa[ 20 ][ 60 ], int & x, int & y, int & jx, int & jy ) { if( x == jx && y == jy ) { jx = rand() % 59; jy = rand() % 19; } mapa[ jy ][ jx ] = '*'; }
Jest jeszcze jeden problem, ponieważ teraz snake jest praktycznie o zerowym poziomie trudności. Chciałbym dodać, aby wraz z czasem snake się sam poruszał w ostatnim wybranym kierunku, lecz nie mam pojęcia jak taki efekt uzyskać. Może miałby ktoś jakieś porady ? :) |
|
pekfos |
» 2013-05-22 14:58:51 Nie zatrzymuj programu na wczytywaniu. |
|
XardassLord Temat założony przez niniejszego użytkownika |
» 2013-05-22 22:51:05 Jeśli chodzi o zatrzymywanie programu przy ruchu to wiem, że te zatrzymanie ogarnicza funkcja getch. Lecz nie wiem, bo nie znam innej, którą mógłbym ją zastąpić ;/ |
|
pekfos |
» 2013-05-23 15:48:30 kbhit() z conio.h sprawdza, czy getch() ma co pobrać (i tym samym, czy nie zatrzyma programu). |
|
« 1 » 2 |