• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Rekurencja i labirynt w języku C

Object Storage Arubacloud
0 głosów
920 wizyt
pytanie zadane 21 listopada 2017 w C i C++ przez Tomek Wilnowski Użytkownik (610 p.)
edycja 21 listopada 2017 przez Tomek Wilnowski
tablica alokowana dynamicznie gdzie przechowuje wartości x i y 
tablica globalna -> char **tablica;
x i y też są globalne 

labirynt:
    ##.####
    ##...##
[...]
wejście x, y w których zapisane są współrzędne labiryntu

bool sciezka(int x, int y){ 
    printf("[%d] [%d]", x, y);
    
    // wsp poza labiryntem, wchodzi gdy prawda
    if(tablica[x][y]==' '){
        return false;
    }
    // sceizka byla ekslorowana, wchodzi gdy prawda
    if(tablica[x][y]==true){
        return false;
    }
    //wsp wyjscia
    if((x==16) && (y==14)){
        printf("Znaleziono droge do wyjscia! [%d][%d]", x, y);
        return true;
    }

    if( sciezka(x+1,y)==true){
        printf("[%d][%d]", x, y);
        tablica[x][y]=true;
        return true;
    }
    if( sciezka(x-1,y)==true){
        printf("[%d][%d]", x, y);
        tablica[x][y]=true;
        return true;
    }
    if( sciezka(x,y+1)==true){
        printf("[%d][%d]", x, y);
        tablica[x][y]=true;
        return true;
    }
    if( sciezka(x,y-1)==true){
        printf("[%d][%d]", x, y);
        tablica[x][y]=true;
        return true;
    }  

    return false;
}

Zadanie polega na znalezieniu wyjścia z labiryntu przy wykorzystaniu rekurencji. Debugowanie tej funkcji pokazuje mi, że parser nie wchodzi w ogóle do żadnego if, ani już w ogóle do tej funkcji po prostu wykonuje ją w nieskończoność sam jej nagłówek. Na razie bym prosił o pomoc w  zrozumieniu tego kodu. W main wykonuje ją w ten sposób.

sciezka(x, y);

Zastanawiam się nad dodaniem trzeciego wymiaru do tablicy gdzie przechowywałbym wartość logiczną 0 którą bym przestawiał na 1 w tedy kiedy dane pole było już sprawdzane przez mój algorytm. Taka flaga.

Co do tego pomysły jak to jest z wartością logiczną w C czy jak przypisze do danej komórki tablicy wartość true, to ona mi się przypisze tak jakbym tworzył dla niej dodatkowy wymiar w sensie czy oprócz mojej wartości # w komórce również będzie zapisywana w tamtej chwili wartość logiczna. Jeśli tak czy zawsze w komórce w tablicy mam zapisaną domyślnie już jakąś wartość logiczną ?

komentarz 21 listopada 2017 przez d0n Mądrala (6,440 p.)
Zmienne nie działają tak, że jak przypiszesz do niej wartość logiczną, to są jakby "dwie zmienne w jednej", zmienna ma jeden, swoj typ i jego sie trzyma, to ze kod się skompilowal, wynika z tego, ze slowo kluczowe true moze byc przyrownane do zmiennej typu char ( zmiennia sie wtedy na znak o kodzie ascii 1 ), ale to totalnie nie jest to, czego chcemy. Zapewne chcesz miec druga tablice typu int  ( albo bool, ale nie pamietam, czy bool bylo w C ), i w niej przechowywac wartosc logiczna, a w tablicy char przechowywac to co wczesniej - znak reprezentujacy dane pole
Jezeli chcesz znalezc sciezke do wyjscia z labiryntu to uzycie rekurencji bedzie bardzo powolne, nawet dla malych gridow i bardzo latwo bedzie ci albo zapetlic kod, albo napisac niepoprawne rozwiazanie ( nie mozna po prostu zaznaczac ze pole jest odwiedzone i do niego nie wracac, tak samo jak trzeba zaznaczac pola ktore sa na aktualnie rozwazanej sciezce, zeby program sie nie zapetlil w nieskonczonosc ), do szukania sciezki do wyjscia z takiego labiryntu sluzy duzo duzo szybciej dzialajacy  i naprawde prosty algorytm przeszukiwania wszerz, tyle, ze nie jest on rekurencyjny.
komentarz 21 listopada 2017 przez Tomek Wilnowski Użytkownik (610 p.)

Dobra dzięki tobie napisałem nieskończoną funkcję rekurencyjną, która tak się zapętla że w efekcie algorytm jest w stanie znaleźć dobrą drogę do wyjścia z labiryntu.

void sciezka(int x, int y){ 
    printf("\n[%d][%d]\n", x, y);
    
    // wsp poza labiryntem, wchodzi gdy prawda
    if(tablica[x][y]==' '){
        return 0;
    }
    // sceizka byla ekslorowana, wchodzi gdy prawda
    if(tablica_flagowa[x][y]==1){
        return 0;
    }
    //wsp wyjscia
    if((x==16) && (y==14)){
        printf("Znaleziono droge do wyjscia! [%d][%d]", x, y);
        return 1;
    }

    if( tablica[x][y]=='.'){
        printf("[%d][%d]", x, y);
        tablica_flagowa[x][y]=1;
        sciezka(x+1,y);
    }
    if( tablica[x][y]=='.'){
        printf("[%d][%d]", x, y);
        tablica_flagowa[x][y]=1;
        sciezka(x-1,y);
    }
    if( tablica[x][y]=='.'){
        printf("[%d][%d]", x, y);
        tablica_flagowa[x][y]=1;
        sciezka(x,y-1);
    }
    if( tablica[x][y]=='.'){
        printf("[%d][%d]", x, y);
        tablica_flagowa[x][y]=1;
        sciezka(x,y+1);
    }
    return 0;
}

Teraz mam pytanie odnośnie przerwania wykonywania tego algorytmu. Problem polega na tym że parser wykonując return 0; wraca mi z powrotem do wykonywania pod funkcji rekurencyjnej z innymi już parametrami, a ja chciałbym, aby gdy już dojdzie do pola 16, 14 program po prostu się zakończył z komunikatem "ble ble" printf("Znaleziono droge do wyjscia! [%d][%d]", x, y); return 0 i return 1 tego nie przerywa.

komentarz 24 listopada 2017 przez d0n Mądrala (6,440 p.)

OK, male sprostowanie:
- instrukcja return 1, czy return 0 to wyjscia z funkcji. najpierw leci return a potem wynik dzialania funkcji.
- to ze w mainie widzimy return 0 konczace dzialanie programu wynika z tego, ze wynik dzialania programu jako zero jest uznawany przez system operacyjny za poprawne zakonczenie dzialania, przed slowkiem main stawia sie zwykle int, co oznacza ze funkcja main zwraca int, czyli po returnie pojawia sie int i tak tez sie dzieje
- ta dluga dygresja prowadzi nas do twojego kodu. jezeli pieszesz w nim return 1, to wyjdziesz po prostu z funkcji i zwroci ona wynik 1. Tzn. zwrocilaby, ale przed nazwa swojej funkcji napisales void - to slowko przed nazwa funkcji oznacza, ze nie zwraca ona wyniku swojego dzialania. 
- zeby uzyskac  to co chcesz musisz jakos uciec z kolejnych wywolan rekurencyjnych, tak zeby wiedzialy ze udalo sie znalezc odpowiednie miejsce
- proponuje to zrobic tak, ze funkcja zamiast void bedzie miala napisane int ( i wtedy musi zwrocic inta ), wtedy kiedy wywolamy glebsze szukanie to mozemy sprawdzic co one zwrocilo - jesli 1 to nie szukamy dalej bo udalo sie znalezc, jesli 0 - nie udalo sie znalezc i przegladamy kolejnych sasiadow wywolujac dalsze funkcje
- oczywiscie jesli jestesmy w odpowiednim polu nasza funkcja powinna zwrocic 1, a jesli przejrzelismy wszystkich sasiadow i nic z tego nie wyszlo to 0
Jeszcze minimalny przykladzik z tym zwracaniem wartosci przez funkcje

int foo ( )
{
 return 1344;
}

int main() {
 printf( "%d", foo() ); // wypisze 1344
}

 

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

+2 głosów
1 odpowiedź 586 wizyt
pytanie zadane 6 czerwca 2017 w Java przez Wiciorny Ekspert (270,170 p.)
0 głosów
1 odpowiedź 1,029 wizyt
0 głosów
2 odpowiedzi 2,411 wizyt
pytanie zadane 4 listopada 2015 w C i C++ przez Lukasz95 Bywalec (2,160 p.)

92,575 zapytań

141,424 odpowiedzi

319,649 komentarzy

61,960 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...