Jak zobrazować algorytm A* w okienku?

0

Witam
Muszę zaimplementować algorytm A* (poszukiwanie drogi w labiryncie). Chciałbym do niego zrobić graficzne wyświetlanie wyniku działania algorytmu w okienku.
Do tej pory nie robiłem GUI, więc nie mam pojęcia jak to zrobić... mam na razie tylko wyświetlanie okienka :P

Labirynt to tablica 10x15 - jak wyrzucić ją na okienko i dodać ruch "bota"? Mogę to zrobić w PHP z rysowaniem labiryntu po każdym kroku, ale wolałbym przy okazji poduczyć się nieco Javy ;) Będę wdzięczny za wszystkie podpowiedzi.

Pozdrawiam serdecznie

0

stany tablicy rysujesz w metodzie paint np. w obiekcie dziedziczącym po JComponet

0

Mam okienko rysowane JFrame - przed chwilą wrzuciłem JComponent, ale jest sporo różnic i nie pokazuje się wcale :)

0

do JFrame dodajesz JComponent :) jako obiekt naniesiony na okienko :)

okno.add(obiekt);

a tak w ogole co sie nie pokazuje JFrame? czy JComponent?

0

Wbrew pozorom rysowanie to najłatwiejsza rzecz jaką można sobie w Swingu wyobrazić.
Tworzysz sobie jakąś listę odwiedzonych miejsc, na której początku jest punkt startowy, a na końcu ostatni punkt odwiedzony algorytmem i uznawany za "czoło". Te miejsca, to mogą być numery pól obszaru podzielonego na pola, współrzędne lub cokolwiek co jest w stanie dla Ciebie zlokalizować miejsce będące częścią drogi na przeszukiwanej przestrzeni.

  1. Tworzysz procedurę paintComponent() w komponencie na którym rysujesz "obraz drogi". Zwykle tym komponentem będzie coś wywiedzione od klasy JPanel.

  2. W algorytmie przeszukującym zajmujesz się tylko dodawaniem lub usuwaniem "punktów" prowadzących do celu. Po każdym dodanym lub usuniętym punkcie wywołujesz repaint(), który informuje Swinga o tym, że coś się zmieniło, narysowany stan nie odpowiada już rzeczywistości i trzeba przerysować stan na nowo.
    Metoda repaint() ma parametry określa obszar przerysowywania. Jest to szczególnie przydatne gdy wiesz, że przerysować trzeba tylko fragment w okolicy końcówki poszukiwanej drogi, a resztę, która jest wcześniej i nie zmieniła się należy zignorować przy renderowaniu obrazu za pomocą paintComponent(). Jednak gdy obliczenia przy rysowaniu nie są bardzo czasochłonne, to można pozostawić repaint bez parametrów co oznacza przerysowanie całej drogi (i całego tła również) od początku do końca.

  3. Zamiast szczegółowo robić repaint co każdy rozpatrywany punkt drogi można też utworzyć osobny wątek, który będzie co jakiś okres czasu (np. timerem) asynchronicznie wywoływał invokeLater() z zawartą procedurą wywołującą jedynie repaint(). Tedy zależnie od częstości wywoływania repain() stan będzie się odrysowywał rzadziej i w stałych odcinkach czasu. Czasem narysuje się więcej, a innym razem mniej (dłuższe obliczenia poszukiwania).

Ponieważ metoda paintComponent() jest wywoływania z jednowątkowego Swinga, to powinna wykonywać się stosunkowo szybko. W idealnym przypadku powinna jedynie rysować na gotowych przygotowanych już w innym wątku danych (współrzędnych elementów graficznych). Można w taki sposób dynamicznie rysować (i kasować też) np. drogę asfaltową z jej zakrętami i prostymi lub chodnik. W prostszej wersji mogą to być ślady stóp rysowane w wyliczonych algorytmem współrzędnych, a w najprostszej po prostu zwykłe linie łączące poszczególne punkty współrzędnych lub nawet po prostu kropki, albo zapalanie i gaszenie kolejnych segmentów szachownicy labiryntu. Cokolwiek przyjdzie do głowy.

Podsumowując. Odpalasz algorytm. który umieszcza na jakiejś liście kolejne współrzędne bieżącej drogi i co jakiś czas lub w wyniku znalezienia kolejnego węzła odpalasz repaint() za pomocą invokeLater(). W paintComponent umieszczasz kod odrysowujący znalezioną drogę napodstawie danych uzyskanych przez algorytm. Jeżeli sam algorytm jest w innym wątku niż kod Swing (zazwyczaj), to musisz synchronizować dostęp do tych samych danych, które z jednej strony aktualizujesz algorytmem przeszukiwawczym, a z drugiej strony odczytujesz za pomocą paintComponent wywoływanej z wątku Swinga. Metoda repaint może zawierać obszar, o którym wiesz, że jako jedyny się zmienia. Wtedy dla pikseli rysowanych przez paintComponent za pomocą (co oczywiste) metod Swinga będzie wykonywana akcja pusta, czyli żadne rysowanie tych punktów nie nastąpi. Mimo, że wszystkie funkcje graficzne zawarte w paintComponent będą się pozornie wykonywać. Sam algorytm A* może być umieszczony w metodzie DoInBackGround() klasy SwingWorker, dzięki czemu odpadnie problem "ręcznej" synchronizacji ze Swingiem.
Jeżeli paintComponent() nie będzie nadążał za kolejnymi wywołaniami repaint(), to żądania odrysowywania przez reaint() będą łączone lub ignorowane.

Tak mniej więcej wygląda rysowanie w Swingu. Można też utworzyć sobie specjalny wątek renderujący z procedurami rysującymi na drugim planie potrzebne elementy tła i drogi (trzeba tylko pamiętać o synchronizacji z danymi modyfikowanymi przez algorytm oraz asynchronicznym wywoływaniu procedur graficznych Swinga. Wtedy sam paintComponent() skróci się do przełączenia strony nieaktywnej na aktywną jeżeli będzie włączone podwójne buforowanie.

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