[C] Ścieżka

Witam. Chciałem poradzić się co do pewnej rzeczy, którą muszę zaprogramować (odnajdywanie drogi w “labiryncie”).

Więc: Użytkownik podaje programowi kolejno rozmiary tablicy: ilość wierszy(n) i ilość kolumn(m). Potem podaje punkt startu[we1][we2] i punkt mety[wy1][wy2]. Na koniec podaje labirynt, gdzie 0 to przejście, -1 to ściana, a -5 start i meta(tworzę labirynt poprzez malloc).

Problem mam z pomysłem jak przechodzić na kolejne pola, tak by wyznaczyć tą najkrótszą z dróg. Napisałem pętlę while, a w niej 4 ify, kiedy ma iść w jaką stronę. Wrzucę tu kawałek kodu dla mety, która jest w wyższym wierszu i wcześniejszej kolumnie niż start. Nie wiem jednak czy to będzie poprawnie działało, nie kompilowałem póki co. Po labiryncie poruszam się wskaźnikiem, który jest modyfikowany poprzez dodawania lub odejmowania odpowiednich wartości (nie mogę używać nawiasów kwadratowych ani vectorów, list czy czegoś podobnego).

if(we1 > wy1)

	{

		if(we2 > wy2)

		{

			while(1)

			{

				if(*(wsk-1) != -1)

				{

					wsk = wsk-1;

					droga++;

				} else if(*(wsk-m) != -1) {

					wsk = wsk-m;

					droga++;

				} else if(*(wsk+m) != -1) {

					wsk = wsk+m;

					droga++;

					if(*(wsk-1) != -1)

					{

						wsk = wsk-1;

						droga++;

					} else if (*(wsk+1) != -1) {

						wsk = wsk+1;

						droga++;

					}

				} else if(*(wsk+1) != -1) {

					wsk = wsk+1;

					droga++;

					if(*(wsk-m) != -1)

					{

						wsk = wsk-m;

						droga++;

					} else if(*(wsk+m) != -1) {

						wsk = wsk+m;

						droga++;

					}

				} else if(wsk == (t+wy1*m+wy2)) {

					printf("%d", &droga);

					return 0;

				}

			}

Jeżeli ktoś miał by jakiś pomysł proszę o wiadomość. Opcjonalnie proszę mi powiedzieć czy moje rozumowanie przyniesie mi sukces. Dzięki.

Tworzymy siatkę 6(wiersze) na 6(kolumny). Punkt startu to pozycja dajmy na to 3 1 a koniec 4 6. Przyjmując że cyfry na minusie to liczba kroków w prawo a cyfra dodatnia to kroki w lewo obliczamy liczbę wierszy do pokonania w tym przypadku 3-4= -1 czyli jeden w prawo. Teraz przyjmujemy że tą samą zasadę do kolumn z taka różnicą że cyfry na minusie to liczba kroków w dół a cyfra dodatnia w góre czyli 6-1= 5 Wynik jeden krok w prawo pięć kroków do góry. TO sposób matematyczny bo w języku C słabo się orientuje, ale mam nadzieje że jakoś pomogłem.

proponuję po czytać o algorytmie A* lub pochodnym alg.

Jak to ma go przybliżyć do określenia która z dróg była najkrótsza? Co jak po drodze wpadniesz na ścianę? Najkrótsza droga nie musi być w linii prostej.

@programator

http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm myślę, że to może pomóc nieco w rozjaśnieniu sprawy.

Twój algorytm jest na 100% zły:

  • brak systematyki, możemy kręcić się po tych samych polach

  • pójście w długi korytarz zakończony ślepą uliczką zmusza nas do wracania i zliczania drogi, której nie musimy przebywać, bo donikąd ona nie prowadzi.

  • co się stanie w twoim algorytmie, jak nie ma wyjścia z labiryntu (zagrodzone ścianami) na moje oko będzie się kręcił bez celu zamiast dojść do wniosku, że nie ma możliwości tego ukończyć.

Dzięki za podpowiedzi. Biorę się za zadanie i będę pisał w razie czego.

Już wczoraj podczas pisania poprzedniego kodu zauważyłem niektóre z jego wad i dlatego zwróciłem się o pomoc.

Napisałem taki kod:

short int *d = t+we1*m+we2;

	short int *k = t+wy1*m+wy2;

	int kroki = 1;


	droga(k, d, kroki, m);


void droga(short int *k, short int *d, int kroki, short int m)

{

	if(*d != 0); 

	{

		break;

	} else if(d == k) {

		printf("%d", &kroki);

	} else {

		*d = kroki;

		kroki++;

	}


	droga(k, d-m, kroki, m);

	droga(k, d+m, kroki, m);

	droga(k, d-1, kroki, m);

	droga(k, d+1, kroki, m);

}

Skompilowało się bez błędów, ale wolałbym, żeby ktoś na to spojrzał. I kolejne pytanie: jak to napisać, żeby program zorientował się, że wszystkie 4 opcje przeskoczenia na następne pola są niemożliwe i wypisał odpowiednie słowa? Mój kod, z tego co widzę, w takiej sytuacji przerwie się i tyle.

Szczerze, nie mam siły analizować, ale już sam fakt ile tu się rozwinie stosów rekurencyjnie przeraża, jeśli chodzi o wydajność

http://en.wikipedia.org/wiki/File:Dijks … mation.gif

chodziło mi o coś takiego, a twoje jak widzę pójdzie maksymalnie w jedna stronę bo nastąpi rozwiniecie pierwszej co do kolejności instrukcji droga potem będzie to zwijane, cóż może da ten sam efekt, ale nie wiem, jeśli chcesz swoje porób testy jednostkowe, i analizuj na kartce.

Ja bym zrobił to iteracyjnie i użył jakiejś prostej kolejki FIFO. Dopóki z kolejki operacja out() nie zwróci nam wyjścia. Bierzemy element i w każda stronę bierzemy sąsiada (wstawiamy do kolejki), oraz przy operacji in() ustawiamy mu jakaś flagę, że został odwiedzony, do kolejki dodajemy tylko tych sąsiadów którzy nie są ściana, i są nieodwiedzeni, jeśli kolejka będzie empty, a nie znaleziono wyjścia, znaczy ze wyjścia nie ma (to jest jeszcze dodatkowy dozór, aby się nie zapętlić).

Twoje rozwiązanie jest kuszące, tyle, że niestety nigdy nie miałem do czynienia z kolejkami FIFO. Jest to trochę dla mnie czarna magia, ale i tak poszukam na internecie i spróbuję coś napisać. Będę aktualizował post, jeżeli coś ciekawego napiszę.

Przy kompilacji mam problem.

Tak sobie tablicę definiuję:

short int n, m;

	short int **t;

	t = (short int**) malloc(n*sizeof(short int*));

	scanf("%d %d", &n, &m);


	for(int i=0;i
	{

		*(t+i) = (short int*) malloc(m*sizeof(short int));

	}

I teraz chciałem wziąć sobie adres startu i przypisać do wskaźnika.

short int *s; 

	s = (t+we1*m+we2);

	short int adres = s;

W kompilatorze mi wyskakuje:

error: cannot convert short int** to short int* in assignment

error: invalid conversion from short int* to short int

Coś nie idzie mi odnoszenie się do wskaźników, wyskakuje sporo błędów. Proszę o pomoc.

chcesz przypisać do wskaźnika na typ wskaźnik na wskaźnik na typ

#include 

#define WALL -1

#define START 2

#define META 3

#define VISITED 4

#define NOT_VISITED 0


struct FIFOQueue {

    int** buffer;

    int begin, end;


    FIFOQueue(int n) {

        buffer = new int*[n];

    }


   void in(int* e) {

        buffer[end++] = e;

    }


    int* out() {

        return buffer[begin++];

    }


    void flush() {

        begin = 0, end = 0;

    }

};


int main() {

    //Tworzenie tablicy dwu wymairowej

    int dim1 = 11;

    int dim2 = 14;

    int** labirynt = new int*[dim1];

    int* dumm = new int[dim1 * dim2];


    for(int i = 0; i < dim1; i++)

        labirynt[i] = dumm + i * dim2;


    //Prosta kolejka FIFO

    FIFOQueue queue(dim1 * dim2);

    queue.flush();


    //Skad zaczynamy

    int* start;


    //Wczytanie wejscia

    for(int i = 0; i < dim1 * dim2; i++) {

        scanf("%d", &dumm[i]);


        if(dumm[i] == START)

            start = &dumm[i];

    }


    //Wyswietlenie poczatkowego labiryntu

    for(int i = 0; i < dim1; i++) {

        for(int j = 0; j < dim2; j++)

            printf("%2d", labirynt[i][j]);

        printf("\n");

    }


    //Umieszczamy cos inicjalnie w kolejce

    queue.in(start);


    //licznik odleglosci

    int counter = 0;


    //wskaznik mowiacy gdzie konczy sie strefa rownych odleglosci

    int* equidistance = start;


    //dopoki cos jest w kolejce

    while(queue.end - queue.begin > 0) {

        int* element = queue.out(); //wez element z kolejki


        *element = VISITED; //odznacz jako odwiedzony


        int* left = element - 1;

        int* right = element + 1;

        int* up = element - dim2;

        int* down = element + dim2;


        if(*left == META || *right == META || *up == META || *down == META) break; //przerwanie gdy doszlismy do mety



        if(*left != VISITED && *left != WALL)

            queue.in(left);

        if(*right != VISITED && *right != WALL)

            queue.in(right);

        if(*up != VISITED && *up != WALL)

            queue.in(up);

        if(*down != VISITED && *down != WALL)

            queue.in(down);


        //debug - printf labiryntu

        for(int i = 0; i < dim1; i++) {

            for(int j = 0; j < dim2; j++)

                printf("%2d", labirynt[i][j]);

            printf("\n");

        }


        printf("%d\n\n", counter);


        //informje kiedy odwiedzilismy wszystkie miejsca w tej samej odleglosci i nakazuje zwiekszyc odleglosc przeszukiwania

        if(element == equidistance) {

            equidistance = queue.buffer[queue.end - 1];

            counter++;

        }

    }


    return 0;

}

Niech strace masz, kod w c++, ale powinienes ogarnąć to do c. Generalnie dość ciekawa sprawa jak to przekierowuje do pliku pod windowsem to mi gdzies w okolicy countera = 11 dopisuje jakies nullowe znaki i inne śmieci. Pod linuksem działą poprawnie. Nie wiem czemu tak się dzieje, ale czesto tak mam np. pod windowsem odmawia mi posłuszeństwa long long. Użyłem takiego oto wejscia do testu. Nie radze printfować na konsoli bo w pliku tekstowym było 61 kb. Jakby co kompilowałem g++.

-1-1-1-1-1-1-1-1-1-1-1-1-1-1

-1-1-1-1-1 0 0 0 0 0 0-1-1-1

-1-1-1-1-1 0 0 0 0 0 0-1-1-1

-1 0 0 0-1-1 0-1-1 0 0-1-1-1

-1 0 0 0-1 0 0 0-1 0 0-1-1-1

-1-1 0-1-1 2 0 0-1 0 0 0 0-1

-1-1 0-1-1 0 0 0-1 0 0 0 0 3

-1-1 0-1-1-1 0-1-1 0 0 0 0-1

-1-1 0 0 0 0 0 0 0 0-1-1-1-1

-1-1 0 0 0 0 0 0 0 0-1-1-1-1

-1-1-1-1-1-1-1-1-1-1-1-1-1-1

Dodane 27.12.2011 (Wt) 22:20

Można jeszcze pomyśleć nad optymalizacja bo kolejka jest naprawde uboga, ale nei chciało mi sie wysilac tylko napisac to na szybko.

Nie, no dzięki. Napisałem już sobie tą kolejkę, bo wiem, że jak ktoś poda kod to jest lipa, a nie nauka. Poszukałem FIFO i przerobiłem trochę, ale bardzo to podobne do listy jednokierunkowej. Praktycznie program jest napisany cały - problem polega na tym, że kompilator krzyczy, że są jakieś błędy. I ja widzę, że to coś ze wskaźnikami. Spróbuję jeszcze swój kod poprawić. Z Twojego też coś może wezmę, żeby nie być jak jakiś pasożyt aby. Swoją drogą ciekawy programik - tylko ja nie mogę używać w nim queue ani nawiasów []. :smiley:

Dzięki jeszcze raz.

short int *s;

s = (t+we1*m+we2);

short int adres = s;

wskazniki potrafia byc flustrujace czasem.

t+we1*m+we2 myśle, że to jest liczba musisz napisać *s = (wyr). gwiazdka przy typie oznacza ze bedzie on przystosowany do przechowywania adresów na tenże typ, ale jak nei jest to deklaracja zmiennej gwiazda oznacza dereferencje, bo s od czasu powiedzenia typ* s jest adresem własnie

short int adres = *s; to samo s to referencja, adres musimy użyc dereferencji zeby wyłuskac wartosc spod adresu.

Dodane 27.12.2011 (Wt) 22:42

Czemu queue, to moja własna implementacja kolejki, nie używam nic poza printfem/scanfem z bibilioteki.

Dodane 27.12.2011 (Wt) 22:47

A co do nawiasów klamrowych, nie rozumiem, ale to proste

tab[2] <=> *(tab + 2) przeuswamy wskaźnik o dwie odległosci typu i pobieramy wartosc

tab[2][1] <=> *(*(tab + 2) + 1) przesuwamy sie po tablicy wskaznikow na typ o dwa to nas przeniesie w jakies miejsce tablicy i z tego miejsca jeszcze o jedna długosc typu

Poprawiłem sobie kolejkę FIFO dzięki Twojemu kodowi, ale teraz mam pytanie jak zastąpić nawiasy kwadratowe w funkcji in(). Niestety, nie mogę ich używać: buffer[end++] = e. Jak to zapisać bez []?

Generalnie end mówi które miejsce w tej tablic jest puste. czyli to robi cos takiego:

//przesun wskaźnik na pierwsze wolne miejsce i wpisz w to miejsce w pamieci wartosc e

*(buffer + end) = e;

//nastepnie zwiększ licznik informujący o tym, gdzie znajduje się kolejne wolne miejsce.

end = end + 1;

Ponadto rozważ czy taka kolejka będzie ci odpowiadać, jest ona szybsza od implementacji na liście o której chyba wspominałeś (brak alokacji/dealokacji w zasadzie tylko jedna niezależnie od rozmiaru danych wejściowych). Ale zużywa (column * row) komórek pamięci naraz, nie wiem jaki masz limit na to zadanie, ale to już sobie obliczysz, czy opłaca ci się przyspieszyć program kosztem pamięci czy robić listę łańcuchową i przesuwanie początku listy (operacja .out()) wiązać z dealokacją.

Dzięki za porady. Poprawiłem wszystko w kodzie i rozpocząłem testy.

Mam małe pytanko do Ciebie jeszcze, jeśli pozwolisz. A właściwie to prośbę.

Testowałem ten swój programik, ale niestety coś jest nie tak.

Dałem mu wejście:

3 5

0 0 2 4

-5 0 -1 -1 -1

-1 0 0 0 -1

-1 -1 0 0 -5

I program po prostu się zakończył, nie ujawniając liczby kroków, które zrobił.

Dałbyś radę przejrzeć go i odpisać czy coś jest nie tak? A definitywnie jest. Jeżeli ja znajdę ten błąd, to napiszę żeby nie zawracać Ci głowy.

Nie chciałbym upubliczniać całej treści kodu z pewnego względu, dlatego jeżeli zgodziłbyś się wysłałbym go w PW albo przekazał po wrzuceniu na jakiś server.

Wyślij prywatną wiadomość, bo poprzednią usunąłeś przed dostarczeniem (z tego co twierdzi system). Moim zdaniem, jeśli bardzo wzorowałeś się na moim, to mój na nim nie zadziałałby, bo labirynt nie jest zewsząd ogrodzony ścianami. Wszystko, zależy jaki jest ten format wejścia, ja przyjąłem, że poprawny labirynt to taki który ma wszędzie dookoła ściany, i nie wyjdziemy sobie poza pamięć, bo wystarczy sprawdzić, czy nie wchodzimy na ścianę.

Dodane 29.12.2011 (Cz) 13:08

Więc tak, masz mete i start jako -5, a do kolejki dodajesz coś jak tylko jest 0, więc to już pierwszy problem, bo nigdy nie dodasz mety, a musisz móc ją zdjąć.

Dwa, to fakt, iż dla twojego labiryntu, jeśli nie jest ogrodzony scianami, a w miejscu poza pamięcią znajdzie się 0, to przeszukiwanie powędruje sobie poza tablice, na stercie nie trudno o taka sytuację. To takie dwa błędy na szybko które znalazłem, poza tym pierwsze co dodajesz inicjalnie to startowy wierzchołek - 5

potem go zdejmujesz i pytasz się czy już nie jestes nad -5, wiec on stwierdza ze tak jesteś nad -5 i urywa program. Musisz rozróznic -5 startowe od -5 mety,np nadpisz start przez - 4. Zachęcam też do używania stałych, bo przy 9-10, będziesz się zastanawiał o co znaczyło 8.

W związku z błędami:

Otoczyłem labirynt użytkownika -1-mi, więc teraz nie ma szans wyjść poza labirynt.

Sprawdziłem też, że dobrze przypisuję adres startowi. Ponadto dobrze zapisuję labirynt.

Zmieniłem z powrotem warunki w ifach w pętli na != -1 i != 2, bo otoczyłem labirynt -1, więc nie ma prawa wyjść poza.

Nadpisałem też start jako 4, więc będzie rozróżnienie między startem i metą. Niestety nadal program zamyka się bez podania jakichkolwiek danych.

Błąd musi być gdzieś w pętli, albo w kolejce(zastanawiałem się nad funkcją wyrzuc() - ona zwraca coś najpierw, a dopiero potem zwiększa początek - czy tak może być? - czy funkcja zwróci po prostu dane pole nie zwiększając przy tym początku?).

Zamieszczam kod w poście. Może ktoś inny dostrzeże jakiś błąd. (Ja piszę na Windzie i dlatego może program nie działa tak jak trzeba?)

Dzięki.

#include 

#include 


struct FIFOkolejka //kolejka FIFO

{

	int poczatek, koniec;

	int **bufor;


	FIFOkolejka(int rozmiar) 

	{

		bufor = (int**) malloc(sizeof(int*)*rozmiar);

	}


	void dodaj(int *p)

	{

		*(bufor + koniec) = p;

		koniec++;

	}


	int *wyrzuc() 

	{

		return *(bufor + (poczatek++));

	}


	void kolor() 

	{

		poczatek = 0, koniec = 0;

	}

};


int main() 

{

	int n, m; // rozmiary labiryntu

	int **t;


	scanf("%d %d", &n, &m);

	// deklaracja tablicy

	n=n+2;

	m=m+2;


	t = (int**) malloc(n*sizeof(int*));


	for(int i=0;i
	{

		*(t+i) = (int*) malloc(m*sizeof(int));

	}

	//wypelniamy obszar poza labiryntem -1

	for(int i=0;i
	{

		*(*(t+0)+i) = -1;

		*(*(t+n-1)+i) = -1;

	}


	for(int i=0;i
	{

		*(*(t+i)+0) = -1;

		*(*(t+i)+m-1) = -1;

	}


	// wczytujemy wspolrzedne startu i mety

	int we1, we2, wy1, wy2;

	scanf("%d %d %d %d", &we1, &we2, &wy1, &wy2);

	we1 = we1+1;

	we2 = we2+1;

	wy1 = wy1+1;

	wy2 = wy2+1;


	// wczytujemy labirynt

	for(int i=1;i
	{

		for(int j=1;j
		{

			scanf("%d", *(t+i)+j);

		}

	}


	if(wy1 < 0 or wy2 < 0 or wy1 > n-2 or wy2 > m-2 or we1 < 0 or we2 < 0 or we1 > n-2 or we2 > m-2)

	{

		printf("NIE WYJDZIESZ ;(");

	} else {

		// tworzymy kolejke o n*m elementach

		FIFOkolejka kolejka(n * m);

		kolejka.kolor();

		// dodajemy start

		int *start = *(t+we1)+we2;

		*start = -4;


		kolejka.dodaj(start);


		int licznik = 0;

		int *rowneodl = start;


		while(1) // glowne dzialanie programu - przechodzenie po kolejnych polach labiryntu

		{

			if(kolejka.koniec - kolejka.poczatek > 0) // jesli kolejka niepusta

			{

				int *pole = kolejka.wyrzuc();


				*pole = 2;


				int *lewo = pole - 1;

				int *prawo = pole + 1;

				int *gora = pole - m; // m ilosc kolumn

				int *dol = pole + m;


				if(*lewo == -5 or *prawo == -5 or *gora == -5 or *dol == -5) // jesli meta - zakoncz; nie powinno tu byc licznik++?

				{

					licznik++;

					printf("%d", licznik);

					break;

				}


				if(*lewo != 2 and *lewo != -1) // sprawdzamy i dodajemy do kolejki

				{

					kolejka.dodaj(lewo);

				}


				if(*prawo != 2 and *prawo != -1)

				{

					kolejka.dodaj(prawo);

				}


				if(*gora != 2 and *gora != -1)

				{

					kolejka.dodaj(gora);

				}


				if(*dol != 2 and *dol != -1)

				{

					kolejka.dodaj(dol);

				}


				if(pole == rowneodl) // zwiekszenie odleglosci

				{

					rowneodl = *(kolejka.bufor + kolejka.koniec - 1);

					licznik++;

				}

			} else { // jesli kolejka pusta wypisz i zakoncz petle

				printf("NIE WYJDZIESZ ;(");

				break;

			}

		}

    }

	return 0;

}

EDIT// Poprawiłem kod według sugestii i faktycznie działa teraz lepiej. Na małych labiryntach działa.

Dopiero dla wejścia:

6 20

5 2 2 17

0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 -1 0 0 0

0 0 0 -1 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0

0 0 0 0 0 0 0 -1 -1 0 0 0 0 0 0 -1 -1 -5 0 0

0 -1 0 0 -1 0 0 0 0 -1 0 0 -1 0 0 0 0 -1 0 0

0 0 0 0 0 0 -1 0 0 -1 0 0 0 -1 0 0 0 0 0 0

0 0 -5 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0

Program się sypnął. Nie dał odpowiedzi i wyszedł.

Dla wejścia:

5 5

2 4 4 2

-1 0 0 0 0

-1 -1 -1 -1 0

0 -1 -1 -1 -5

-1 0 0 0 0

-1 -1 -5 0 -1

Program dał odpowiedź: 6 (powinno wyjść 4).

Coś tutaj nie do końca gra.

Ok dzięki. I tak dużo już mi pomogłeś.

Taa, nie zauważyłem tego, nie zwiększasz początku, bo return wychodzi wcześniej.

zapisz to tak return *(bufor + (poczatek++));

dałem te dodatkowe nawiasy na wszelki wypadek, ale chyba nie są potrzebne z tego co pamiętam postinkrementacja ma wyższy priorytet od całej reszty

Poza tym w pierwszym kodzie w warunkach dodawania masz OR czego tez nie zuważyłem, powinno być and inaczej dodasz coś zawsze jesli a =/= x lub a =/= y to jest tautologia dla bo a nie moze byc jednoczesnie x i y aby to kiedy kolwiek zwróciło fałsz (chyba ze x = y)

Dodane 29.12.2011 (Cz) 18:56

Nie mam pojęcia o co chodzi, ale pod windowsem mi się na moim programie ten labirynt wywala błąd to (0xC0000005), a pod unixem wyrzuca 22 kroki. Dziś ci już raczej nie dam rady pomóc bo mam jeszcze kilka spraw do załatwienia. Ale i tak wątpie, może “pogooglanie” za tym kodem błędu coś da.

Dla drugiego mój zwraca 4, musiałeś coś poknocić w algorytmie, albo w otaczaniu ścianami, ja dodaje to po chamie do wejścia (zakładam, że labirnynt będzie zabezpieczony) i wtedy działa. Może juto przepisze to na C, ale muszę usiąść z manualem do niego bo nigdy nie pisałem w czystym C.Przy czym zaznaczam, pod windowsem się sypie na unixie działa, nie wiem czemu.

Dodane 31.12.2011 (So) 14:30

Dobra wymęczony, ale nadal ten duży labirynt sypie się pod mingw (code::blocks) na windowsie, pod gcc na linuksie działa, zwraca 22, tak jak sprawdziłem ręcznie, ten mały działa i pod windowsem i pod uniksem.

#include 


#define WALL -1

#define START -4

#define FINISH -5

#define VISITED 2

#define NOT_VISITED 0


#define DEBUG //Usunac te linijke aby pozbyc sie debugow w kodzie


//START FIFO

struct FIFO {

    int** buffer;

    int begin, end;

} fifo;


void FIFOConstructor(int fieldsNo) {

    fifo.buffer = (int**) malloc(sizeof(int*) * fieldsNo);

}


void flush() {

    fifo.begin = 0;

    fifo.end = 0;

}


void in(int* e) {

    *(fifo.buffer + fifo.end++) = e;

}


int* out() {

    return *(fifo.buffer + fifo.begin++);

}

//END FIFO


int main() {

    int columns, rows, startX, startY, finishX, finishY, i, j, counter = 0;

    int* dumm, *equidistance;

    int** labirynt;


    scanf("%d %d %d %d %d %d", &rows, &columns, &startY, &startX, &finishY, &finishX);


    columns += 2; rows += 2;

    startX += 1; finishX += 1;

    startY += 1; finishY += 1;


    //Przenioslem do przodu, bo nie ma sensu wczytywac wejscia, jak dostalismy dane spoza obszaru labiryntu, poprostu dajemy odpowiedź i konczymy program

    if(startX < 1 || startX > columns - 2 || finishX < 1 || finishX > columns - 2 || startY < 1 || startY > rows - 2 || finishY < 1 || finishY > rows - 2) {

        printf("BRAK WYJSCIA");

        return 0;

    }


    //alokacja labiryntu

    labirynt = (int**) malloc(sizeof(int*) * rows);

    dumm = (int*) malloc(sizeof(int) * rows * columns);


    for(i = 0; i < rows; i++)

        *(labirynt + i) = dumm + i * columns;


    //tworzenie kolejki fifo

    FIFOConstructor(columns * rows);


    // obramowanie

    for(i = 0; i < columns; i++) {

        *(*(labirynt + 0) + i) = WALL;

        *(*(labirynt + rows - 1) + i) = WALL;

    }


    for(i = 0; i < rows; i++) {

        *(*(labirynt + i) + 0) = WALL;

        *(*(labirynt + i) + columns - 1) = WALL;

    }


    #ifdef DEBUG

        printf("Obramowanie:\n");

        for(i = 0; i < rows; i++) {

            for(j = 0; j < columns; j++)

                printf("%3d", *(*(labirynt + i) + j));

            printf("\n");

        }

        printf("\n");

    #endif


    // wczytywanie labiryntu

    for(i = 1; i < rows - 1; i++)

        for(j = 1; j < columns - 1; j++)

            scanf("%d", &(*(*(labirynt + i) + j)));


    *(*(labirynt + startY) + startX) = START;


    #ifdef DEBUG

        printf("Labirynt:\n");

        for(i = 0; i < rows; i++) {

            for(j = 0; j < columns; j++)

                printf("%3d", *(*(labirynt + i) + j));

            printf("\n");

        }

        printf("\n");

    #endif


    //Umieszczamy start inicjalnie w kolejce

    in(&(*(*(labirynt + startY) + startX)));


    #ifdef DEBUG

        printf("Kolejka inicjalnie:");

        for(i = fifo.begin; i < fifo.end; i++) {

           printf(" %d", *(*(fifo.buffer + i)));

        }

        printf("\n\n");

    #endif


    //wskaznik mowiacy gdzie konczy sie strefa rownych odleglosci

    equidistance = &(*(*(labirynt + startY) + startX));


    while(fifo.end - fifo.begin > 0) {

        int* element, *left, *right, *up, *down;


        element = out();

        *element = VISITED;


        left = element - 1;

        right = element + 1;

        up = element - columns;

        down = element + columns;


        if(*left == FINISH || *right == FINISH || *up == FINISH || *down == FINISH) {

			counter++;

			break;

		}


        if(*left != VISITED && *left != WALL)

            in(left);

        if(*right != VISITED && *right != WALL)

            in(right);

        if(*up != VISITED && *up != WALL)

            in(up);

        if(*down != VISITED && *down != WALL)

            in(down);


        #ifdef DEBUG

            for(i = 0; i < rows; i++) {

                for(j = 0; j < columns; j++)

                    printf("%3d", *(*(labirynt + i) + j));

                printf("\n");

            }

            printf("\n");

        #endif


        if(element == equidistance) {

            equidistance = *(fifo.buffer + fifo.end - 1);

            counter++;

        }

    }


    #ifdef DEBUG

        for(i = 0; i < rows; i++) {

            for(j = 0; j < columns; j++)

                printf("%3d", *(*(labirynt + i) + j));

            printf("\n");

        }

        printf("\n");

    #endif


	printf("%d\n", counter);


    return 0;

}

Nie znalazłem powodu wysypywania się tej aplikacji pod windowsem kod błędu taki sam jak powyżej. Tam jeszcze nie dodałem warunku jak patrze na to ze kolejka jest zero a wyjścia nie możemy znaleźć, bo jest np. ogrodzenie zewsząd ścianami trzeba to dodać. Nie mniej ja już na dziś spadam z wiadomych sylwestrowych przyczyn. :stuck_out_tongue: