Labirynt, przejście od lewej do prawej

Labirynt, przejście od lewej do prawej
0

Mam zadanie, zrobić program, który sprawdza czy labirynt da się przejść z lewej do prawej. Do programu wpisuje się 8 cyfr, które są zamieniane na system 0-1. 0 to ściana a 1 to droga:

37 00100101
136 10001000
196 -> 11000100
96 01100000
127 01111111 <- ten labirynt da się przejść.
37 00100101
42 00101010
42 00101010

Mam już taki generator, ale nie mam pomysłu jak sprawdzi, czy labirynt da się przejść. Jeżeli ktoś może mi pomóc, to bardzo bym prosił, i z góry dzięki za odpowiedzi.

Misiekd
  • Rejestracja:ponad 21 lat
  • Ostatnio:ponad 12 lat
  • Postów:7923
0

jeśli tylko masz sprawdzić czy da się przejść to możesz zrobić tak, że zawsze skręcasz w lewo a jak trafisz na koniec tunelu to zawracasz. Jak dojdziesz do prawej strony to jest przejście a jak do wejścia to nie ma


- Ciemna druga strona jest.
- Nie marudź Yoda, tylko jedz tego tosta.
Google NIE GRYZIE!
Pomogłem - kliknij
0

A jak mam to zrobić, If , pętla, czy może rekurencja ? Ja nie mam pojęcia jak sią za to zabrać ;/.

Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 6 godzin
0

Ten sposób działa na labirynty w których nie ma przejść cyklicznych. W przeciwnym razie możesz zacząć się kręcić wokoło. Wyobraź sobie mieszkanie z drzwiami z pokoju A do B, z B do C i z C do A: mimo trzymania się cały czas jednej strony, nigdy nie trafiasz na balkon…

edytowany 3x, ostatnio: Azarien
0

No właśnie mi się zdaje, że coś z If trzeba kombinować, i z każdej 1 po lewej zobaczyć jak daleko można zajść, aż się dojdzie do prawej. Nie wiem tylko jak sprawdzać kolejną cyfrę w rzędzie i przechodzić do linijki wyżej i niżej.

ŁF
Moderator
  • Rejestracja:ponad 22 lata
  • Ostatnio:8 dni
0

algorytm flood fill, chociaż nie wiem, czy nie jest nadmiernie skomplikowany w stosunku do tego typu zadań. linki do przykładów znajdziesz na google (i o dziwo na youtube) - labyrinth flood fill.
algorytm proponowany przez Miśkad też sobie poradzi, bo w takim labiryncie nie ma przejść cyklicznych, musisz tylko sprawdzić, czy nie wróciłeś do punktu startu (jeśli tak się stanie,to znaczy, że balkonu jednak nie ma ;)).

"if, pętla czy rekurencja" - wszystkie trzy (chociaż da się i bez rekurencji). jeśli nie umiesz wyobrazić sobie działania algorytmu i zaimplementować go, to nie startuj do takich zadań.


edytowany 2x, ostatnio: ŁF
0

Nie startował bym, ale to praca semestralna z informatyki. Labirynt musi być podany w formie cyfr i program ma zamienić cyfry na system binarny i utworzyć z tego labirynt. To wszystko już mam ale nie wiem jak sprawdzić tą drogę, w labiryncie składającego się z poszczególnych pól (jak kratka w zeszycie z zamalowaną częścią kratek). Myślałem nad if (po lewej stronie) 1 then i szuka dookola tej jedynki innych. jak znajdzie to tak aż trafi na prawą stronę labiryntu.

0

Niewielka modyfikacja rekurencyjnego algorytmu do przeszukiwania grafu (wgłąb albo wszerz) załatwi sprawę.

GL
  • Rejestracja:około 14 lat
  • Ostatnio:około 14 lat
  • Postów:6
1

Ja proponuję zrobić tak:
z tych stringów zrobić tablicę dwuwymiarową booleanów. jeśli jest ścieżka w punkcie [i,j] to wartość true, jeśli nie, to false.
dodatkowo zadeklarować sobie tablicę [1..64] rekordów [x,y] (rekord zawiera 2 integery które są współrzędnymi jakiegoś punktu)

37 00100101
136 10001000
196 -> 11000100
96 01100000
127 01111111 <- ten labirynt da się przejść.
37 00100101
42 00101010
42 00101010

np, dla tego labiryntu wartość [1,1] będzie false, [1,8] false, [3,1] true, itd (pierwsza współrzędna rośnie poziomo w prawo, druga pionowo w dół - 0,0 to górny lewy róg).

skonstruowanie takiej tablicy nie jest trudne - wystarczy utworzyć stringi z danych liczb w systemie (wystarczy włączyć bibliotekę STRUTILS, i można zamienić dowolną liczbę w sys. dziesiętnym na stringa zerojedynkowego, i nawet dodać ile się chce zer wiodących)

np.

Kopiuj
uses strutils;
var s: string; i: integer;
begin
read(i);
s:=binStr(i, 8);
end.

string 's' będzie zawierał zera i jedynki zapisane w 8 charach, z zerami wiodącymi.

potem wystarczy skanować ten string, i ustawiać w tablicy odpowiednie wartości - true/false.

i potem:
skanujesz sobie tę utworzoną tablicę. jeśli w jakimś miejscu [1, i] jest wartość true, to znaczy że można tutaj zacząć zwiedzanie labiryntu. zaczynasz więc zwiedzanie. jeśli z danego punktu prowadzi tylko jedna droga do innego punktu, to wymazujesz z tablicy aktualną pozycję (na aktualnej pozycji ustawiasz FALSE, zapewnia to potem stabilność programu i zapobiega zapętleniom przy powrotach do rozwidleń). sprawdzenie możliwych dróg można bardzo łatwo wykonać:
jeśli jesteś w punkcie [i,j] to wystarczy sprawdzić:

  • [i-1,j]
  • [i+1, j]
  • [i, j-1]
  • [i, j+1]
  • jeśli w sumie na tych pozycjach jest więcej niż jedno true, to znaczy że z pozycji [i,j] prowadzi więcej niż jedna droga. analogicznie, jeśli nie ma żadnego true, znaczy że doszedłeś do ślepego zaułka. gdy dojdziesz do rozwidlenia, używasz tablicy rekordów o której wspominałem wcześniej. najlepiej trzymać zmienną dotyczącą tych rekordów, która będzie wskazywała na jakiej pozycji skończyłeś dopisywanie rekordów. np. jeśli dopisałeś 5 rekordów, to zmienna wskazująca na kolejne dopisanie=6. i po prostu gdy trzeba, odwoływać się do kolejnego rekordu (trzeba pamiętać o zwiększaniu 'wskazywacza' po każdym odwołaniu się do rekordu).
    i teraz tak:
  • jeśli jest jedna droga, to idziesz nią, i wymazujesz swój ślad.
  • jeśli napotkasz się na rozwidlenie, dodajesz punkt w którym jest rozwidlenie, na pozycji w tablicy rekordów, którą wskazuje ci wskazywacz zapisywania. idziesz dowolnie wybraną drogą, i robisz analogicznie - gdy jest to jedna droga, wymazujesz, jeśli nie, zapisujesz współrzędne rozwidlenia. gdy dojdziesz do jakiegoś indeksu [8, i] to znaczy że wyszedłeś z labiryntu. jeśli dojdziesz do ślepego zaułka, to:
    a) jeśli masz jakiś rekord wskazujący na rozwidlenie, sprawdzasz, w których kierunkach możesz z niego iść, i idziesz. jeśli nie ma żadnego kierunku w którym możesz iść, to wracasz do poprzedniego rozwidlenia, i tam sprawdzasz czy możesz iść, itd, aż nie będziesz miał żadnych rekordów wskazujących na rozwidlenia w tym korytarzu. w takim wypadku, skanujesz kolejne linie, aż natkniesz się na kolejne wejście do labiryntu które ma indeks [1, i], i tam wykonujesz to samo błądzenie.
    b) jeśli nie ma już żadnych rekordów wskazujących na rozwidlenia, i żadnych innych wejść do labiryntu, odpowiedź brzmi nie.
    c) jeśli doszedłeś do jakiegoś indeksu [8,i] (w sumie nawet nie trzeba do niego dochodzić - wystarczy, że dotrzemy do indeksu [7,i] i sprawdzimy czy w miejscu [8,i] jest TRUE - jeśli jest, to jest to wyjście z labiryntu) to odpowiedź brzmi TAK

jeśli masz jakieś pytania, to wal :P

przykładowy przebieg algorytmu dla tego labiryntu:

37 00100101
136 10001000
196 -> 11000100
96 01100000
127 01111111 <- ten labirynt da się przejść.
37 00100101
42 00101010
42 00101010

skanujesz tablicę. pierwszym wejściem jest [1,2] z którego prowadzi tylko jedna droga do [1,3]. w miejscu 1,2 ustawiasz FALSE aby nie próbować drugi raz wejść tym wejściem i się nie zapętlić. jesteś w 1,3, i robisz tak jak poprzednio. idziesz do 2,3 jedyną drogą, potem do 2,4 gdzie jest rozwidlenie (bo jest więcej niż jedna sąsiadująca komórka która ma TRUE). dodajesz współrzędne rozwidlenia do tablicy na pierwszej pozycji, jednocześnie w głównej tablicy ustawiając wartość FALSE w miejscu rozwidlenia. zwiększasz pozycję kolejnego zapisania na 2. idziesz dowolną drogą, przypuśćmy, że do 3,4. jedyna droga jest do 3,5, gdzie jest rozwidlenie. ustawiasz tam false, i dodajesz na pozycji drugiej współrzędne rozwidlenia. tym razem wybierasz drogę w dół, osiągasz punkt [3,8] który jest ślepym zaułkiem (po drodze trzeba pamiętać o wymazywaniu odwiedzonych ścieżek przez ustawianie FALSE). tak więc wracasz do ostatnio dodanego rekordu, którym jest nr 2. (aktualna pozycja zapisywania jest na 3, więc ostatnio dodany rekord jest na miejscu 3-1). tak więc wracasz do punktu 3,5 z którego prowadzi teraz dwie drogi - na prawo i na lewo. idziesz na lewo do 2,5. masz tylko jedną drogę do 2,4, gdzie jest ślepy zaułek (zauważ, że podczas wcześniejszego wykonywania algorytmu, wymazaliśmy ścieżki w miejscu 2,3 i 3,4, więc pozycję 2,4 program odczyta jako ślepy zaułek. wracasz w takim razie do 3,5. prowadzi z niego już tylko jedna droga, więc można wymazać ten rekord z tablicy, i ustawić pozycję zapisywania na 2 (na pozycji pierwszej mamy punkt 2,4 - gdybyśmy się do niej odwołali, to byłoby 0 możliwych ścieżek, i wymazalibyśmy go również - ale program tego nie wie, więc zostawia sobie ten rekord zapamiętany). idziemy więc z rozwidlenia 3,5 jedyną możliwą ścieżką, zamazując. dochodząc do 6,5 mamy rozwidlenie. zamazujemy go, dodajemy współrzędne tego rozwidlenia na poz. 2. idziemy w dół, gdzie jest ślepy zaułek. wracamy się więc do ostatnio dodanego rozwidlenia 6,5. i tym razem idziemy jedyną możliwą ścieżką. dochodzimy do 7,5. w tym miejscu, sprawdzając możliwe ścieżki, dowiadujemy się, że na pozycji [8,5] jest true, co jest równoznaczne z wyjściem z labiryntu. odpowiedź pozytywna.

edytowany 1x, ostatnio: gles
MX
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 13 lat
0

Ja bym jednak zrobił tak jak Mariusz BFS-a (z kolejką) - do kolejki wrzucasz na początku kilka punktów startowych, robisz BFS-a, jak natrafisz na punkt wyjścia zwracasz true, inaczej false.


Not Found
The requested URL /wypasiona_sygnaturka.txt was not found in this brain.
-----
Human/1.0.00 (Earth) Server at Poland Port 65535
edytowany 2x, ostatnio: mnbvcX
GL
  • Rejestracja:około 14 lat
  • Ostatnio:około 14 lat
  • Postów:6
0

przykładowe funkcje i procedury do programu:

Kopiuj
function IleMozliwych(i,j: integer):integer; //przekazujemy wspolrzedne punktu w ktorym jestesmy aby sprawdzic na ile sposobow mozemy z niego wyjsc
begin
IleMozliwych:=0;
if labirynt[i-1,j]=TRUE then inc(ilemozliwych);
if labirynt[i+1,j]=TRUE then inc(ilemozliwych);
if labirynt[i,j+1]=TRUE then inc(ilemozliwych);
if labirynt[i,j-1]=true then inc(ilemozliwych);
end;

fragment odpowiedzialny za dodawanie rozwidleń

Kopiuj
//jesteśmy  punkcie i,j. pozycja zapisywania =3 (tzn, dodaliśmy już wcześniej 2 rozwidlenia)
if IleMozliwych(i,j) > 1 then 
begin
      with rozwidlenia[pozycja_zapisywania] do 
      begin
         x:=i; y:=j; 
      end;
      inc(pozycja_zapisywania);
end;
labirynt[i,j]:=false

edit: trzeba jeszcze zadeklarować zmienną, (rekord x,y) który będzie wskazywał na aktualną pozycję w labiryncie, i odpowiednio ją zmieniać przy zwiedzaniu. możemy wejść tylko na pole TRUE, któremu ustawiamy FALSE po wejściu na nie. gdy dotrzemy do miejsca gdzie IleMozliwych=0 to ustawiamy aktualna pozycje na ostatnie rozwidlenie i tam działamy od nowa.

edytowany 1x, ostatnio: gles
0

Dziękuję za tyle odpowiedzi. Zaraz zaczynam coś kombinować tylko muszę jeszcze zrozumieć działanie tablicy 2 wymiarowej.

ŁF
Moderator
  • Rejestracja:ponad 22 lata
  • Ostatnio:8 dni
0

nie mam pod ręką kompilatora delphi, więc napisałem w c# implementację przejścia przez labirynt z wykorzystaniem algorytmu flood fill:
static bool floodFillSolver(string[] l)
{
int h = l.Length, w = l[0].Length;

// przepisanie tablicy 1D stringów na tablicę 2D charów (w c# nie można bezpośrednio modyfikować znaków w stringu)
var f = new char[h, w];
for (int i = 0; i < h; i++)
	for (int j = 0; j < w; j++)
		f[i, j] = l[i][j];

// pętla po wszystkich elementach pierwszej kolumny - "miejsca startu", czyli jedynki w pierwszej kolumnie
for (int i = 0; i < h; i++)
{
	if (f[i, 0] == '1')
	{
		f[i, 0] = '2';

		bool changed = false;
		
		// flood fill:
		// ilość przebiegów - ekstremalny przypadek w/2*h/2, na wypadek, gdyby 
		// ścieżka wielokrotnie zasuwała pod górkę albo w lewą stronę; ze względu
		// na optymalizację kończącą pętlę po wykryciu pustego przebiegu równie 
		// dobrze może to być pętla nieskończona
		for (int n = 0; n * 4 < w * h; n++)
		{
			// jeśli w przebiegu nie został zmieniony żaden element, 
			// to stan mamy ustalony i koniec flood filla
			for (int x = 0; x < h; x++)
				for (int y = 0; y < w; y++)
				{
					if (f[y, x] == '2')
					{
						if (x == w - 1) // dwójka w ostatniej kolumnie - flood fill dotarł do prawego brzegu
							return true;

						// sprawdzenie, czy w sąsiedztwie dwójki znajdują się 1, jeśli tak, to zmieniane w 2
						if (y > 0     && f[y - 1, x] == '1') { f[y - 1, x] = '2'; changed = true; }
						if (x > 0     && f[y, x - 1] == '1') { f[y, x - 1] = '2'; changed = true; }
						if (y < h - 1 && f[y + 1, x] == '1') { f[y + 1, x] = '2'; changed = true; }
						if (x < w - 1 && f[y, x + 1] == '1') { f[y, x + 1] = '2'; changed = true; }

					}
				}

			// optymalizacja - zlikwidowanie pustych przebiegów (jeśli 
			// w tej iteracji flood fill nic się nie zmieniło, to w następnej
			// też się nie zmieni); break zamiast return false ze wzgledu na
			// możliwość wielu punktów startowych (patrz pierwsza pętla)
			if (!changed) break;
		}
	}
}

return false;

}

Kopiuj

wywołanie:
<code class="c#">Console.WriteLine(floodFillSolver(new string[] {
	"00100101",
	"11111011",
	"11001010",
	"10001010",
	"10111010",
	"10100110",
	"10101010",
	"10111110"
}));

oczywiście całość można przerobić na operowanie na tablicy 1d bajtów/intów/czegokolwiek, ale mi się nie chciało, a w c# najłatwiej było 2d char.


edytowany 1x, ostatnio: ŁF
ŁF
kojot rozwalił nieco formatowanie, zastępując każdego taba ośmioma, a nie czterema spacjami :/
Riddle
A nie znasz składni delphi na pamięć?
0

A co polecacie na labirynt z cyklami?

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)