Gra Snake, problem z zawracaniem

0

Przepraszam za temat ale ciężko mi to jakoś nazwać. Napisalem grę typu Snake pod consola w win xp. Problem mój polega na tym że gdy szybko zawróce to wąż zamiast zawrócić tak jak to powinno byc zawraca w miejscu tak że głowa wjeżdża na ciało węża. Nie wiem też jaki fragmęt kodu zamieścić bo jest on dość obszerny więc zamieszczam to co najważniejsze chyba. Oczywiście chciał bym tak zrobić by taka sytuacja nie mogła zaistnieć ale raczej nie kosztem czegoś.


  put_food();
  draw_board();
  
  do
  {
        znak = 0; 
        
        while ( !kbhit() )
        {

                end = GetTime() + ms1/(speed * 100);
                
                move(); // zmiana wspolrzednych weza zaleznie od kierunku
                check_colision(); // sprawdzenie kolizji
                draw_food(); // rysowanie jedzenia
                draw_snake() // rysowanie weza
                
                
                if ( G_State == GS_OVER ) return points; //  check_colision modyfikuje G_State

                points += map_event();   // obsluga zdarzen na mapie i zsumowanie z nich pkt    
                       
                gotoxy(80,24);
                waitms(ms1/speed, true);

        }
        if ( G_State == GS_OVER ) return points;

        if( !Obsluz_zdarzenie( znak = getch(), points ) ) return -1; // obsluga wcisnietego klawisza
                                                                        // czyli przypisanie odpowiednich wspolrzednych glowie
        tm_left = 50 * (end - GetTime());
        if ( tm_left > 0 ) waitms( tm_left, false); // doczekanie do czasu end

  }while (1);

Jeżeli mam coś jeszcze zamieścić piszcie.
Szukałem troche samemu ale nie znalazłem węża napisanego w c++ który nie ma tego błędu.

0
  1. Dodaj sobie flagę np bool flaga i w miejscu w którym przechwytujesz wciśnięty klawisz daj po przechwyceniu flaga = true;
  2. Dodaj warunek, jeżeli flaga == true to nie przechwytujesz klawiszy.
  3. W pętli while daj na górze flaga = false;

Takie cóś spowoduje że podczas jednego przejścia pętli while tylko raz zczytasz klawisze.

0

dzieki wielkie za odpowiedz jeszcze nie zdazylem przetestowac niestety, ale z tego co widze to raczej zadziala;] wiec temat do zamkniecia;]

0

po dogłębnym sprawdzeniu mogę powiedzieć że działa jednak nie satysfakcjonuje mnie takie rozwiazanie bo ( tu nie wiem jak to znowu powiedziec ) zawraca w taki sposob:
----->
|

(strzalka to glowa) chodzi o to ze nie da sie zawrocic tak:

--------->

wydaje mi się że coś takiego miałeś na myśli


bool flaga = true;
do
  {
        znak = 0; 
        
        while ( !(flaga && kbhit())  )
        {
              
                if ( flaga && kbhit() ) break;
                
                flaga = true;
                end = GetTime() + ms1/(speed * 100);
                
                
                move();
                check_colision();
                draw_food();
                draw_snake();

                if ( G_State == GS_OVER ) return points;

                points += map_event();   // obsluga zdarzen na mapie i zsumowanie z nich pkt    
                     
                gotoxy(80,24);
                waitms(ms1/speed, true);                

        }
        
        if ( G_State == GS_OVER ) return points;

        if( !Obsluz_zdarzenie( znak = getch(), points ) ) return -1;
        
       flaga = false;
        tm_left = 50 * (end - GetTime());
        if ( tm_left > 0 ) waitms( tm_left, false); // doczekanie do czasu end

  }while (1);
0

Pokaż co masz w move() i Obsluz_zdarzenie()

0

spoko;]

bool Obsluz_zdarzenie( char sign, int score )
{
       if ( !sign ) return false;
       switch(sign)
       {
                   case 72://strzalka w gore
                   {
                       if ( kierunek != DIR_DOWN ) kierunek = DIR_UP;
                       break;
                   }
                   case 80://strzalka w dol
                   {
                       if ( kierunek != DIR_UP ) kierunek = DIR_DOWN;
                       break;
                   }
                   case 75://strzalka w lewo
                   {
                       if ( kierunek != DIR_RIGHT ) kierunek = DIR_LEFT;
                       break;
                   }
                   case 77://strzalka w prawo
                   {
                       if ( kierunek != DIR_LEFT ) kierunek = DIR_RIGHT;
                       break;
                   }
                   case 112://klawisz p
                   {
                      pause( score );
                      clrscr();
                      textcolor(7);
                      draw_board();
                      break;
                   }
                   case 27: // klawisz ESC
                   {
                        return false;
                   }
                   default : break;
       }
       return true;
}
/********************************************/
bool move()
{
     if ( G_State != GS_PLAY ) return false;
     int i;      

     for ( i = length - 1; i > 0; i-- ) // zmiana wspolrzednych n-tego elementu na wspolrzedne n-1 elementu
     {
       Snake[i].x = Snake[i - 1].x;
       Snake[i].y = Snake[i - 1].y;
     }
     switch(kierunek)//zmiana wspolrzednych glowy
     {
         case DIR_UP:
         {
              Snake[0].y--;
              break;
         }
         case DIR_DOWN:
         {
              Snake[0].y++;
              break;
         }
         case DIR_LEFT:
         {
              Snake[0].x--;
              break;
         }
         case DIR_RIGHT:
         {
              Snake[0].x++;
              break;
         }
     }

     return true;
}
0

Rozumiem że DIR_DOWN itd to definicje liczb prawda?

Spróbuj coś takiego, mogą być błędy w składni ale powinno działać:

bool Obsluz_zdarzenie( char sign, int score )
{
       if ( !sign ) return false;
       switch(sign)
       {
                   case 72://strzalka w gore
                   {
                       if (( kierunek != DIR_DOWN ) && (kierunekFaktyczny != DIR_DOWN) ) kierunek = DIR_UP;
                       break;
                   }
                   case 80://strzalka w dol
                   {
                       if ( (kierunek != DIR_UP) && (kierunekFaktyczny != DIR_UP) ) kierunek = DIR_DOWN;
                       break;
                   }
                   case 75://strzalka w lewo
                   {
                       if (( kierunek != DIR_RIGHT )  && (kierunekFaktyczny != DIR_RIGHT) )kierunek = DIR_LEFT;
                       break;
                   }
                   case 77://strzalka w prawo
                   {
                       if (( kierunek != DIR_LEFT ) && (kierunekFaktyczny != DIR_LEFT) ) kierunek = DIR_RIGHT;
                       break;
                   }
                   case 112://klawisz p
                   {
                      pause( score );
                      clrscr();
                      textcolor(7);
                      draw_board();
                      break;
                   }
                   case 27: // klawisz ESC
                   {
                        return false;
                   }
                   default : break;
       }
       return true;
}
/********************************************/
bool move()
{
     if ( G_State != GS_PLAY ) return false;
     int i;      

     for ( i = length - 1; i > 0; i-- ) // zmiana wspolrzednych n-tego elementu na wspolrzedne n-1 elementu
     {
       Snake[i].x = Snake[i - 1].x;
       Snake[i].y = Snake[i - 1].y;
     }
     switch(kierunek)//zmiana wspolrzednych glowy
     {
         case DIR_UP:
         {
              Snake[0].y--;
			  kierunekFaktyczny = DIR_UP;
              break;
         }
         case DIR_DOWN:
         {
              Snake[0].y++;
              kierunekFaktyczny = DIR_DOWN
			  break;
         }
         case DIR_LEFT:
         {
              Snake[0].x--;
			  kierunekFaktyczny = DIR_LEFT
              break;
         }
         case DIR_RIGHT:
         {
              Snake[0].x++;
			  kierunekFaktyczny = DIR_RIGHT;
              break;
         }
     }

     return true;
}

Tą flagę możesz pewnie wyrzucić jeśli to zadziała.

0

DIR_UP to typ wyliczeniowy enum
jego deklaracja wyglada tak: enum DIRECTION { DIR_UP, DIR_DOWN itd }

ale to już nie ważne bo zadziałało:)) ogromne dzięki.
Jeszcze miał bym prośbę jeśli zauważyłeś jakieś głupie rzeczy w tych fragmentach kodu żebyś mi powiedział ewentualnie nakierował jak inaczej pisać.

PS Kliknij tutaj http://ghostsnake1.webpark.pl/ jeśli chciał byś zobaczyć jak wygląda całość.

1 użytkowników online, w tym zalogowanych: 0, gości: 1