Na tej mapie „stały ląd” to cały ląd, który można połączyć ze środkiem mapy w czterech głównych kierunkach (północ, południe, wschód, zachód - nie po przekątnej).
Chciałbym wykryć kontynent i wypełnić w nim dziury. Myślałem o trzech rzeczach:
Szukaj w każdej komórce innej niż woda (ciemne komórki), jeśli można ją połączyć ze środkiem mapy za pomocą algorytmu znajdowania ścieżki. Za drogie! Ale to może zadziałać na wyspach.
Kontynent jest wypełniony wiadrem zielonej farby. Każda dziura jest otoczona farbą ... co teraz? Jeśli sprawdzę sąsiedztwo każdego punktu wody na kontynencie, usunę niektóre półwyspy i inne elementy geograficzne wyświetlane na linii brzegowej.
Jakiś rodzaj wykrycia krawędzi, aby dowiedzieć się o kontynencie. Trzymaj wszystko, co jest w środku, napełnij je wodą, usuń to, co jest na zewnątrz. Złożony?
Być może jakiś doświadczony programista może mi w tym pomóc, podając nazwę znanego algorytmu lub techniki?
Odpowiedzi:
Usuwanie wysp
Robiłem takie rzeczy wcześniej w jednej z moich gier. Aby pozbyć się zewnętrznych wysp, proces polegał zasadniczo na:
Usuwanie jezior
Jeśli chodzi o pozbycie się dziur (lub jezior) na wyspie, wykonujesz podobny proces, ale zaczynasz od narożników mapy i zamiast tego rozprzestrzeniasz się przez kafelki „Wody”. Pozwoli ci to odróżnić „Morze” od innych kafelków wody, a następnie możesz się ich pozbyć, tak jak wcześniej wysp.
Przykład
Pozwól mi wykopać moją implementację wypełnienia zalewowego, które gdzieś tu mam (zrzeczenie się odpowiedzialności, nie dbałem o wydajność, więc jestem pewien, że istnieje wiele bardziej wydajnych sposobów na jej wdrożenie):
Wykorzystałem to jako pierwszy krok do pozbycia się jezior w mojej grze. Po nazwaniu tego, wszystko co musiałem zrobić, to:
Edytować
Dodanie dodatkowych informacji na podstawie komentarzy. W przypadku zbyt dużej przestrzeni wyszukiwania może wystąpić przepełnienie stosu podczas korzystania z rekurencyjnej wersji algorytmu. Oto link na stackoverflow (zamierzone słowo :-)) do nierekurencyjnej wersji algorytmu, używając
Stack<T>
zamiast tego (również w języku C #, aby dopasować moją odpowiedź, ale powinna być łatwa do dostosowania do innych języków, a istnieją inne implementacje na ten temat link też).źródło
Zmodyfikuj cztero-kierunkowy algorytm wypełniania zalania http://en.wikipedia.org/wiki/Flood_fill
źródło
Jest to standardowa operacja przetwarzania obrazu. Używasz operacji dwufazowej.
Zacznij od utworzenia kopii mapy. Z tej mapy zamień w piksele morskie wszystkie piksele lądowe, które graniczą z morzem. Jeśli zrobisz to raz, wyeliminuje 2x2 wyspy i zmniejszy większe wyspy. Jeśli zrobisz to dwa razy, wyeliminuje wyspy 4x4 itp.
W fazie drugiej robisz prawie odwrotnie: zamieniaj w piksele lądowe wszystkie piksele morskie, które graniczą z lądem, ale tylko wtedy, gdy były pikselami lądowymi na oryginalnej mapie (dlatego wykonałeś kopię w fazie 1). Spowoduje to przywrócenie wysp do ich pierwotnej postaci, chyba że zostaną całkowicie wyeliminowane w fazie 1.
źródło
Miałem podobny problem, ale nie w rozwoju gier. Musiałem znaleźć piksele na obrazie, które sąsiadowały ze sobą i miały tę samą wartość (połączone regiony). Próbowałem użyć rekurencyjnego wypełniania, ale ciągle powodowałem przepełnienie stosu (jestem początkującym programistą: P). Następnie wypróbowałem tę metodę http://en.wikipedia.org/wiki/Connected-component_labeling , w rzeczywistości była o wiele bardziej wydajna, jak na mój problem.
źródło