Optymalizacja Snake'a oraz ulepszenie metody kończącej grę.
Ostatnio zmodyfikowano 2017-06-17 15:55
eXhaustedPL Temat założony przez niniejszego użytkownika |
Optymalizacja Snake'a oraz ulepszenie metody kończącej grę. » 2017-06-16 20:33:35 No heja wszystkim! Właśnie jestem na finiszu pisania konsolowego snejka, którego chciałbym później przenieść do SFMLa. Jednak mam malutki problem - otóż nie wiem jak opisać metodę, która kończyłaby grę, gdy głowa węża będzie chciała zjeść swój tułów. Kolizję z krawędziami mam oprogramowaną. No i drugi problem - otóż wąż porusza się oraz wydłuża poprawnie, jednak na kliknięcie jakiejkolwiek strzałki reaguje z małym, lecz odczuwalnym opóźnieniem. Tutaj zamieszczam swój kod: #include <iostream> #include <cstdlib> #include <ctime> #include <conio.h> #include <windows.h>
using namespace std;
const int UP = 72, DOWN = 80, LEFT = 75, RIGHT = 77;
class Single_Area { bool food; bool band; bool head; friend class Area_and_Snake; friend void play(); public: Single_Area() { food = false; band = false; head = false; } void place_food() { food = true; } void place_band() { band = true; } void place_head() { head = true; } void remove_head() { head = false; } void remove_food() { food = false; } void draw_snake() { cout << "@"; } };
class Area_and_Snake { Single_Area ** T; int * tail_x; int * tail_y; int N; int M; int x_coordinate; int y_coordinate; int step; int length; char key; int direction; friend void play( Area_and_Snake board ); public: Area_and_Snake() { length = 0; step = 0; cout << "Jakich wymiarow chcesz, by byla plansza? Podaj ilosc wierszy: "; cin >> N; cout << "Podaj ilosc kolumn: "; cin >> M; T = new Single_Area *[ N ]; for( int i = 0; i < N; i++ ) { T[ i ] = new Single_Area[ M ]; } tail_x = new int[ 10000 ]; tail_y = new int[ 10000 ]; x_coordinate = 5; y_coordinate = 5; T[ x_coordinate ][ y_coordinate ].place_head(); } ~Area_and_Snake() { for( int i = 0; i < N; i++ ) { delete[] T[ i ]; } delete[] T; delete[] tail_x; delete[] tail_y; T = NULL; tail_x = NULL; tail_y = NULL; } void set_food( int n, int m ) { srand( time( NULL ) ); n = 1 + rand() %( N - 2 - 1 + 1 ); m = 1 + rand() %( M - 2 - 1 + 1 ); T[ n ][ m ].place_food(); } void create_borders() { for( int i = 0; i < N; i++ ) { T[ i ][ 0 ].place_band(); T[ i ][ M - 1 ].place_band(); } for( int i = 1; i < M; i++ ) { T[ 0 ][ i ].place_band(); T[ N - 1 ][ i ].place_band(); } } void increase_length() { length++; } void display() { for( int i = 0; i < N; i++ ) { cout << endl; for( int j = 0; j < M; j++ ) { if( T[ i ][ j ].band ) cout << "#"; else if( T[ i ][ j ].food ) cout << "o"; else if( T[ i ][ j ].head ) cout << "@"; else cout << " "; } } } void move_snake() { if( kbhit() ) { key = getch(); if( key == UP ) direction = 1; if( key == DOWN ) direction = 2; if( key == LEFT ) direction = 3; if( key == RIGHT ) direction = 4; } step++; tail_x[ step ] = x_coordinate; tail_y[ step ] = y_coordinate; if( direction == 1 ) { y_coordinate--; T[ tail_y[ step - length ] ][ tail_x[ step - length ] ].remove_head(); T[ y_coordinate ][ x_coordinate ].place_head(); } else if( direction == 2 ) { y_coordinate++; T[ tail_y[ step - length ] ][ tail_x[ step - length ] ].remove_head(); T[ y_coordinate ][ x_coordinate ].place_head(); } else if( direction == 3 ) { x_coordinate--; T[ tail_y[ step - length ] ][ tail_x[ step - length ] ].remove_head(); T[ y_coordinate ][ x_coordinate ].place_head(); } else { x_coordinate++; T[ tail_y[ step - length ] ][ tail_x[ step - length ] ].remove_head(); T[ y_coordinate ][ x_coordinate ].place_head(); } } void if_over() { if( T[ y_coordinate ][ x_coordinate ].head == T[ y_coordinate ][ x_coordinate ].band ) { cout << "\n\nPrzegrales! :(\n\n"; exit( 0 ); } else return; } void if_food() { if( T[ y_coordinate ][ x_coordinate ].head == T[ y_coordinate ][ x_coordinate ].food ) { T[ y_coordinate ][ x_coordinate ].remove_food(); increase_length(); set_food( 0, 0 ); } } };
void play( Area_and_Snake board ) { board.create_borders(); board.set_food( 0, 0 ); board.display(); while( true ) { Sleep( 70 ); board.move_snake(); board.if_food(); board.if_over(); system( "CLS" ); board.display(); } }
main() { Area_and_Snake board; play( board ); return 0; }
Metoda odpowiedzialna za kończenie gry (gdy pozycja głowy węża jest równa pozycji bandy to koniec gry, jak go mogę zmodyfikować, by się też kończyła gra gdy wąż chce zjeść siebie samego?: void if_over() { if( T[ y_coordinate ][ x_coordinate ].head == T[ y_coordinate ][ x_coordinate ].band ) { cout << "\n\nPrzegrales! :(\n\n"; exit( 0 ); } else return; }
Mogłbym Was prosić o pomoc w sprawie kończenia gry i poprawienia czasu reakcji na wciśnięcie klawisza? Dzięki za pomoc! :) |
|
latajacaryba |
» 2017-06-16 21:12:48 Tak się składa, że właśnie pisze snake (tylko na innych zasadach, dla dwóch graczy) w SFML i ja to robie tak: Każdy segment ciała ma wskaźnik na kolejny, czyli: class Segment { Segment * next; int PosX; int PosY; }
Oczywiście okrojona wersja. I teraz patrzysz, czy pozycja głowy (1 element) == pozycja innych elementów. Najlepiej mieć tablice jako mapę: Segment * ptr; = next;
while( ptr != nullptr ) { if( ptr->PosX == PosX && ptr->PosY == PosY ) return false; ptr = ptr->next; }
return true;
Generalnie to tylko ogólny zamysł, jeszcze tego nie implementowałem ale taki mam plan. |
|
pekfos |
» 2017-06-16 22:38:35 Każdy segment ciała ma wskaźnik na kolejny |
Po co implementować listę za każdym razem, gdy potrzebujesz listy? Nie wystarczy ci std::list<> do tego? if( T[ y_coordinate ][ x_coordinate ].head == T[ y_coordinate ][ x_coordinate ].band )
|
Czy przypadkiem x/ y_coordinate to nie jest zawsze pozycja głowy? Wystarczy samo T[y_coordinate][x_coordinate].band jako warunek. |
|
eXhaustedPL Temat założony przez niniejszego użytkownika |
» 2017-06-17 15:33:54 Faktycznie, wystarczy tylko sprawdzać położenie bandy ;) Trywialne rozwiązanie, nie wiem czemu chciałem być "bardziej papieski niż papież" i tak napisałem :P
Ale dalej mam problem z kolizją węża, nie mam zupełnie pomysłu jak rozbudować warunek, by się kończył też, gdy głowa się kończyła z kolizją tułowia. Prawdę powiedziawszy to tułów jest głową, której ostatni element jest sukcesywnie usuwany. |
|
pekfos |
» 2017-06-17 15:55:37 Może sprawdzaj przed wykonaniem ruchu, czy na polu docelowym głowy już jest 'głowa'. |
|
« 1 » |