Ciągły ruch węża...

0

Witam, mam taki oto kod:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <ncurses.h>
	int k;
	int xMax, yMax;
	int kierunek(char c);

int main()
{
	
	int seed;
	seed = time(NULL);
	srand(seed);
	struct cialo
	{
    char c;
    int x,y,kierunek;
    unsigned int rozmiar_weza;
	};
	
	struct zarcie
	{
    char c;
    int x,y;
        };
        int a,b;
        
        struct zarcie jedzenie;
        struct cialo waz;
	initscr();
	noecho();
	cbreak();
	curs_set(0);
	keypad(stdscr, TRUE);
	getmaxyx(stdscr, yMax, xMax);
	border('|','|','-','-','+','+','+','+');
	refresh();
	waz.c = '*';
  	waz.x = xMax/2;
  	waz.y = yMax/2;
  	waz.rozmiar_weza = 1;
  	waz.kierunek = 0;
  	mvwprintw(stdscr, waz.y, waz.x, "%c", waz.c);
  	refresh();
  	jedzenie.c = '8';
        jedzenie.y = rand()%yMax;
  	jedzenie.x = rand()%xMax;
  	mvwprintw(stdscr, jedzenie.y, jedzenie.x, "%c", jedzenie.c); /*zamiast osobno move i wprintw*/
  	refresh();
  	
  	while(1)
  	{
  	k = direction( getchar() );
  	waz.kierunek = k;
  	switch(waz.kierunek)
		{
		case 1:
		{
		mvwprintw(stdscr, --waz.y, waz.x, "%c", waz.c);
        	              mvwprintw(stdscr, (waz.y+waz.rozmiar_weza), waz.x, " "); /*zamalowanie ""*/
                            break;
        	             	}
		
		
		case 2:
		{	
		mvwprintw(stdscr, ++waz.y, waz.x, "%c", waz.c);
        	mvwprintw(stdscr, (waz.y-waz.rozmiar_weza), waz.x, " ");
        	break;
		}
	
		
		case 3:
		{
		mvwprintw(stdscr, waz.y, --waz.x, "%c", waz.c);
        	mvwprintw(stdscr, waz.y, (waz.x+waz.rozmiar_weza), " ");
        	break;
		}
		
		case 4:
		{
		mvwprintw(stdscr, waz.y, ++waz.x, "%c", waz.c);
        	mvwprintw(stdscr, waz.y, (waz.x-waz.rozmiar_weza), " ");
        	refresh();
        	break;
		}
		}
		refresh();
		
		if ( waz.y == jedzenie.y && waz.x == jedzenie.x)
    		{
      ++waz.rozmiar_weza;
      jedzenie.y = rand()%yMax;
      jedzenie.x = rand()%xMax;
      mvwprintw(stdscr, jedzenie.y, jedzenie.x, "%c", jedzenie.c);
      refresh();
		}
	}
	endwin();
	return 0;	
}	  	

int kierunek(char c)
{
  switch (c)
  {
    case 'w': return 1; 
    case 's': return 2;      
    case 'a': return 3;       
    case 'd': return 4;       
    case 'q': return -1; 
  }
}
 

Już od kilku godzin męczę się z tym, że jak dam pętlę np. while (k == 1) to wąż porusza się sam, ale nie reaguje już na inne klawisze. Nie wiem jak zrobić żeby poruszał się w określonym kierunku, dopóki nie wcisnę innego klawisza. Bardzo proszę o pomoc.

0
Visher napisał(a)

Taki sposób jest bez sensu. Za każdym ruchem czyścisz ekran i rysujesz wszystko od nowa - wydajność zerowa.
Używaj biblioteki conio2 - tam masz bardzo dobre funkcje, m.in. putchxy(x, y, 'a') który wstawia znak 'a' na pozycję x, y. Także jest clrscr() do czyszczenia ekranu, gotoxy(x, y) do przesunięcia kursora w dane miejsce wiersza poleceń. Stosując putchxy będziesz na jeden ruch zmieniał tylko dwie rzeczy :)
No i jak już pisałem, poczytaj o vectorach, będziesz miał w bardzo oszczędnej pamięciowo wersji wszystkie elementy snake'a.

I co do poruszania się, zrealizuj to tak:

char key;
int relPosX, relPosX

if (kbhit()) // Jeżeli w buforze klawiatury jest jakiś znak
{
	key = getch();
	
	switch (key)
	{
		case 'w':
			relPosX = 0;
			relPosY = -1;
			break;
		case 's':
			relPosX = 0;
			relPosY = 1;
			break;
		case 'a':
			relPosX = -1;
			relPosY = 0;
			break;
		case 'd':
			relPosX = -1;
			relPosY = 0;
			break;
		default:
			break;
	}
}

Sleep(800);

I obliczasz sobie następną pozycję na którą wejdzie snake.

Sleep() masz w windows.h

0

Taki sposób jest bez sensu. Za każdym ruchem czyścisz ekran i rysujesz wszystko od nowa - wydajność zerowa.

No tak, bo przerysowanie ekranu konsoli zajmuje całe wieki. NCurses sobie z tym bez żadnego problemu poradzi.

Używaj biblioteki conio2 - tam masz bardzo dobre funkcje, m.in. putchxy(x, y, 'a') który wstawia znak 'a' na pozycję x, y. Także jest clrscr() do czyszczenia ekranu, gotoxy(x, y) do przesunięcia kursora w dane miejsce wiersza poleceń. Stosując putchxy będziesz na jeden ruch zmieniał tylko dwie rzeczy :)

Conio zamiast NCurses?? Biblioteka która swoje złote lata przeżywała w czasach MS-DOS-a :| ?

No i jak już pisałem, poczytaj o vectorach, będziesz miał w bardzo oszczędnej pamięciowo wersji wszystkie elementy snake'a.

Rada słuszna, ale motywacje niekoniecznie. Zużycie pamięci nie ma nic do rzeczy - parę bajtów, dajmy na to kilobajt straty różnicy nie czyni...

PS. wybacz offtopic, ale do komentarza się nie mieściło.

0

Niestety musi być w ansi c, więc wektory odpadają. Musi być również ncurses. Czy jest jakaś możliwość aby bez wielkich modyfikacji to działało??

0

ustaw timeout na zero i getch będzie działać nieblokująco (będzie zwracać ERR gdy nie ma dostępnych znaków).

The timeout and wtimeout routines set blocking or non-blocking read for a given window. If delay is negative, blocking read is used (i.e., waits indefinitely for input). If delay is zero, then non-blocking read is used (i.e., read returns ERR if no input is waiting). If delay is positive, then read blocks for delay milliseconds, and returns ERR if there is still no input. Hence, these routines provide the same functionality as nodelay, plus the additional capability of being able to block for only delay milliseconds (where delay is positive).

0

Marku a mógłbyś mi to pokazać, po prostu nie używałem wcześniej takiej funkcji. Przy okazji chciałbym zapytać jak zrobić aby program reagował na polecenie ./a.out -h albo -help. Wiem że trzeba użyć getopt ale coś mi nie wychodzi.

0

Ale czy to nie jest oczywiste? po prostu w części inicjalizacyjnej dopisujesz timeout(0); . Korzystasz z fragmentu kodu jaki ci dał Visher (bez kbhit, bo to pochodzi ze złej biblioteki) i to powinno zadziałać.

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