Snake w c++

0

Witam, jakiś czas temu zacząłem programowanie w szkole i nawet mnie to zaciekawiło.
Pokusiłem się o napisanie snake, ale już mam pierwszy błąd, kod nie jest długi bo nie chciałem pisać dalej, gdy nie rozwiązałem tego błędu.
Ciężko opisać na czym polega błąd najlepiej samemu to zobaczyć, chodzi o to, że podchodząc do lewej bocznej i górnej ściany (w komórce 0) głowa węża się nie wyświetla od razu, trzeba zrobić dodatkowy ruch w bok (w przypadku podejścia do górnej ściany) lub w górę/dół (przy bocznej lewej ścianie).
Kod zamieszczam w załączniku oraz wklejam, oto kod:

#include <iostream>
#include <cstdio>
#include <conio.h>
#include <windows.h>


using namespace std;

////////////////////////////////////
//        zmienne globalne       ///
//								 ///
char map[20][60]; //mapa         ///
int sx=30, sy=10; //pozycja weza ///
//								 ///
//        zmienne globalne       ///
////////////////////////////////////


void rysuj() //mapa
{
	cout << " ------------------------------------------------------------" << endl; //ramka
    for(int i=0;i<20;i++)
    {
		cout << "|"; //ramka
    	for(int j=0;j<60;j++)
        {
			map[i][j]=255;
			if(sx==j && sy==i) map[i][j]='O'; //wpisanie weza
			cout << map[i][j];
		}
		cout << "|"; //ramka
        cout << endl;
    }
	cout << " ------------------------------------------------------------"; //ramka
     
};

int ruch() //sterowanie wezem
{
	int odp=getch();
	if(odp=='w')
	{
		map[sy][sx]=255;
		sy--;
		if(sy<0) sy=19;
	}else if(odp=='a')
	{
		map[sy][sx]=255;
		sx--;
		if(sx<0) sx=59;
	}else if(odp=='s')
	{
		map[sy][sx]=255;
		sy++;
		if(sy>19) sy=0;
	}else if(odp=='d')
	{
		map[sy][sx]=255;
		sx++;
		if(sx>59) sx=0;
	}
	
}


//////////////////////////////////
////////////PROGRAM///////////////
//////////////////////////////////
int main()
{
    rysuj();
    while(true) 
	{
		if(ruch())
		{
			system("cls");
			rysuj();
		}
	}

    
    getchar();
    return 0;
}
1

int ruch a nie ma żadnego returna? to jak ten if działa w mainie? tamta funkcja powinna coś zwracać. np return odp; na końcu. Po tej zmianie nie widziałem nic takiego co Ty wypisujesz (dodatkowy ruch)

 if(ruch())
1

ten system("cls") mnie dobija weż stwórz stringa ze zawartością ekranu i na nim narysuj tą całą planszę, później wystarczy ,że cofniesz kursorem na początek konsoli i coutem wyświetl ten cały string. W ten sposób przynajmniej ekran nie będzie migał.

0

Co do ruch() to jak daję void to nie działa, jednak dziękuję, dałem return odp; i jest w porządku, ale w takim razie czemu, gdy nie było return odp; to program działał tylko był ten błąd (?).
robcio, wytłumacz dokładnie o co Ci chodzi, początkujący jestem.

1

"Podstawy mam, a tu szukam pomocy. - Hiraki" Przepraszam za offtop, ale juz krew mnie zalewa...
CALOSC zawarta w tym tutorialu to sa podstawy tego jezyka http://www.cplusplus.com/doc/tutorial/

Teraz, a propos kodu:

  1. Zmienne globalne sa brzydkie i ich sie nie robi, kiedy naprawde nie trzeba.
  2. funkcja rysuj() jest zakomentowana, ze sluzy do narysowania mapy, a tu psikus bo rysuje wszystko.
  3. funkcja ruch() nie powinna sie w zaden sposob odwolywac do mapy
  4. wykrywanie kolizji ze scianami ( w przyszlosci moze dojdziesz do jablek) powinno byc napisane oddzielnie, a nie w funkcji ruch, samo pobranie wejscia od uzytkownika, odswiezenie pozycji gracza i wykrycie kolizji to powinny byc min 3 funkcje, a na pewno nie w jednej
  5. to if(ruch()) to kpina, ale to juz chyba zrozumiales.
  6. nie planujesz rozszerzania tego weza?
  7. w tej ideologii zrobiony kod ladnie bedzie chodzil, na 1 komputerze, na 2 i na 5, ale, ale za 10 lat nie bedziesz w stanie zobaczyc nawet tego weza

cos na plus:
Fajnie, ze starasz sie komentowac kod, tylko naprawde przemysl co moze byc niejasne dla czytajacego i to zakomentuj. Pisanie rzeczy oczywistych mija sie z celem np. //ZMIENNE GLOBALNE

1

Przecież @fasadin podał Ci już odpowiedź. Musisz coś zwracać w funkcji ruch(). Dodam tylko, że nikt tutaj Cię nie atakuje, tylko pokazuje, jak nie należy programować.

 
int ruch() //sterowanie wezem
{
        int odp=getch();
        if(odp=='w')
        {
                map[sy][sx]=255;
                sy--;
                if(sy<0) sy=19;
        }else if(odp=='a')
        {
                map[sy][sx]=255;
                sx--;
                if(sx<0) sx=59;
        }else if(odp=='s')
        {
                map[sy][sx]=255;
                sy++;
                if(sy>19) sy=0;
        }else if(odp=='d')
        {
                map[sy][sx]=255;
                sx++;
                if(sx>59) sx=0;
        }
        return 1;
}
0

Mógłby ktoś wytłumaczyć to o czym mówił robcio?

0

Chodzi o to, żeby pozbyć się czyszczenia konsoli i w zamian każdą "klatkę" mapy wrzucać do stringa/strumienia. Każde rysowanie mapy zaczynasz od przesunięcia kursora na początek mapy i wyświetlasz tego stringa/strumień.

0

Mhm, a jak to zrobić?

1

Lub drugi sposób - napisać funkcje która przyjmuję współrzędną X,Y na ekranie oraz nowy znak który ma być 'namalowany' na ekranie. Do snaka powinna być w sam raz.

coś ala

void zastap(unsigned int x, unsigned int y, char znak)
{
    gotoxy(x,y);
    cout << znak;
}

wywal zmienne globalne a sam ruch zrób sobie dla uproszczenia w main() coś na wzór

    do
    {
        clrscr();
        if (kbhit())
            znak = getch();

        if (znak == 'w')
            y--;
        if (znak == 's')
            y++;
        if (znak == 'a')
            x--;
        if (znak == 'd')
            x++;

        gotoxy(x,y);
        cout << "#";

        Sleep(100);

    } while (znak != 27);
0

gotoxy nie działa w nowej wersji programu (pracuję w Dev-c++) poza tym to przesuwa kursor w wyznaczone przez nas miejsce, więc jak to się ma do migania ekranu i jak to ma pomóc?
Ehm... pomyliłem SetCursosPos() z gotoxy()... w każdym razie jest jakaś alternatywa do niego? Bo jak pisałem nie działa w nowym Devie.

Mam od kolegi coś takiego :D

void GotoXY(short x, short y) {
COORD coord = {x, y};
HANDLE l_hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

SetConsoleCursorPosition(l_hConsole, coord);
}
1

pomyśl - nie czyścisz ekranu w ogóle tylko podmieniasz konkretne znaki które tego wymagają.

Np. Jeśli wąż porusza się w dół to wywołujesz

zastąp(x,y,' '); // (dla ogonu)
zastąp(x,y+1,'#'); // (dla głowy)

A czy użyjesz funkcji prosto z api czy z innego źródła nie ma znaczenia.

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