Dokumentacja do projektu rozwiązania problemu konika
Transkrypt
Dokumentacja do projektu rozwiązania problemu konika
Dokumentacja do projektu rozwiązania problemu konika
szachowego (Knight’s Tour)
1. Dane autora:
Imię i nazwisko: Karol Laskowski
Grupa ćw: 3
Rok: I
Data: 25.05.2007
2. Opis problemu:
Jednym z klasycznych zadań algorytmicznych jest odnalezienie drogi konika szachowego przy załoŜeniu, Ŝe kaŜde pole
szachownicy jest odwiedzane tylko jeden raz.
ZałoŜenia:
Szachownica ma wymiar n x n.
Konik porusza się według reguł obowiązujących w grze w szachy.
Konik rozpoczyna ruch po szachownicy od podanego pola o współrzędnych x i y.
KaŜde pole moŜe być odwiedzone tylko raz.
Problem ten na wiele sposobów próbowali rozwiązać wielcy matematycy począwszy od de Mairan’a w 1725 i Eulera w 1759.
Początkowo korzystano z algorytmu z powrotami, jednak był on dość nieefektywny, działał powoli i wykonywał zbyt duŜo
operacji. W 1823 H. C. von Warnsdorff, w swojej pracy Des Rösselsprunges einfachste und allgemeinste Lösung {„Proste i
glowne rozwiązanie drogi konika szachowego”} przedstawił opracowany przez siebie algorytm pozwalający w prosty sposób
przejść całą szachownicę. Zakładał on, Ŝe następny ruch konika z dowolnego pola na szachownicy powinien skierowac go na
pole, z którego jest z kolei najmniej moŜliwości ruchu. Na tym algorytmie opiera się opisywany program.
3. Opis podstawowych algorytmów:
Algorytm Warnsdorff’a opiera się na załoŜeniu, Ŝe konik szachowy w swoim następnym ruchu skacze na pole (jedno z kilku
moŜliwych), z którego jest najmniej moŜliwości ruchu. Na podstawie tego algorytmu napisałem dwie podstawowe funkcje w
programie: best oraz funkcję główną main. Najpierw w funkcji main (blok „Wyszukiwanie drogi konika...”) powtarza sie pętla
wykonywania ruchów. W niej za kaŜdym razem pod zmienną i podstawiana jest wartość kierunku ruchu na pole z najmniejszą
moŜliwością ruchu. Następnie warunek sprawdza czy funkcja best prawidłowo odnajduje drogę (jeśli zwraca 0 to znaczy, Ŝe nie
istnieje rozwiązanie problemu dla danej szachownicy i pól startowych). Jeśli wszystko jest w porządku (best zwraca niezerowy
nierunek) to konik wykonuje ruch w kierunku i, zwiększa numer ruchu i dodaje nowy element za wierzch stosu. Następnie po
odnalezieniu(bądź nie) drogi dla konika zawartość stosu zapisywana jest do tablicy. Jeśli algorytm nie znajdzie drogi dla konika,
na tablicy pozostają pola o wartości 0.
Kilka pojęć:
Szachownica – dynamiczna tablica dwuwymiarowa, po której w programie „skacze” konik szachowy.
Stos – lista dynamiczna o elementach typu struct pole zawierająca informacje o kolejnych współrzędnych ruchu konika na
szachownicy, numerach ruchów i kierunkach ruchów.
Kierunek ruchu – rodzaj ruchu konika na szachownicy z jednego pola na nastepne wg oficjalnych reguł gry w szachy. Z jednego
pola jest maksymalnie 8 moŜliwych kierunków ruchu. MoŜliwe kierunki przedstawia tabelka. Numery to kierunki z pola
oznaczonego S:
3
2
4
1
S
5
8
6
7
4. Opis implementacji zaprojektowanego systemu
•
•
•
•
IDE i kompilator: Dev-C++ ver. 4.9.9.2
Wykorzystane moduły standardowe dostarczane wraz z IDE: biblioteki ‘stdlib.h’, ‘stdio.h’
Wykorzystane moduły niestandardowe: biblioteka ‘conio2.h’ dostępna od wersji IDE Dev-C++ ver. 4.9.9.2 (w
wersjach poprzednich dostępna po pobraniu uaktualnienia z internetu)
Wykorzystane typy: róŜne standardowe typy danych języka C, struct pole utworzona na potrzeby programu, struct
char_info oraz struct text_info z biblioteki ‘conio2.h’
•
•
•
•
Pliki źródłowe programu niezbedne do prawidłowego utworzenia programu: plik projektu Dev-C++
‘Warnsdorff.dev’ oraz plik z kodem źródłowym ‘main.c’
Funkcje standardowe: malloc, calloc, free, printf, scanf, getch
Funkcje niestandardowe z biblioteki ‘conio2.h’: inittextinfo, gettextinfo, _setcursortype, gettext, textbackground,
textcolor, clrscr, gotoxy
Funkcje utworzone w programie: ruch, mozna, best, push, del1, wyswietlb, do_tab,wysw_pkt, show_tab, ostatni,
poprz, main
Opisy działania funkcji:
void ruch(int lp, int *pozx, int *pozy)
SłuŜy do wykonania ruchu z pola o współrzędnych (pozx, pozy) w kierunku lp. Wartości są przekazywane do programu przez
wskaźniki. Do współrzędnych połoŜenia konika dodaje odpowiednie przesunięcie na płaszczyźnie szachownicy wg tabelki
kierunków. Przykładowo przy wartościach początkowych lp=2, pozx=4, pozy=5 funkcja zwróci wartości pozx=5, pozy=3.
int mozna(int i, int pozx, int pozy, pole *pierwszy)
Funkcja sprawdza czy moŜliwy jest ruch w kierunku i z pola (pozx, pozy). Bierze pod uwagę czy pole na które chcemy ruszyć
znajduje się jeszcze na szachownicy i czy nie jest juŜ zajęte (sprawdza to w stosie). Zwraca 1 jeśli spełnione są te warunki lub 0
jeśli przynajmniej jeden z nich nie jest spełniony. Korzysta z funkcji ruch.
int best(pole *lista, int xx, int yy)
Jedna z waŜniejszych funkcji. Zwraca kierunek na pole z najmniejszą moŜliwością ruchu. Najpierw będąc na polu początkowym
(xx, yy) za pomocą pętli sprawdza kaŜdy kierunek w jakim moŜna ruszyć z tego pola. Dla kaŜdego z moŜliwych kierunków
następna pętla oblicza ilość moŜliwych ruchów i zapisuje ją do pomocniczej tablicy il_ruch. Następnie sprawdza który z
elementów tej tablicy jest najmniejszy(który kierunek z pola(xx, yy) ma najmniej moŜliwości ruchu) wyłączając kierunki, które
nie mają Ŝadnej moŜliwości. Indeks najmniejszego niezerowego elementu tablicy to optymalny, zgodny z załoŜeniem algorytmu
kierunek ruchu konika. JeŜeli jednak kaŜdy kierunek ma 0 moŜliwości ruchu(pozostało ostatnie pole na szachownicy) to kolejna
pętla wyszukuje kierunek, w którym wogóle moŜna ruszyć. Wykorzystuje funkcje mozna i ruch.
pole *push(pole *pierwszy, int x, int y, int z)
Dodaje nowy element na wierzch stosu i nadaje mu wartości x(współrzędna X), y(współrzędna Y), z(numer ruchu na to pole).
Zwraca wskaźnik na wierzchołek stosu.
pole *del1(pole *pierwszy)
Jeśli pierwszy (wierzchołek stosu) istnieje (jest róŜny od NULL) to jest usuwany(zwalniana pamięć) i funkcja zwraca wskaźnik na
początek stosu.
void wyswietlb(struct pole *pierwszy)
Jeśli pierwszy (wierzchołek stosu) istnieje (jest róŜny od NULL) to funkcja rekurencyjnie wyświetla stos zaczynając od elementu
na jego spodzie. W ten sposób wyswietla się go rozpoczynając od pola startowego.
void do_tab(pole *pierwszy, int szach[rozmiar][rozmiar])
Zapisuje do juŜ utworzonej dynamicznej tablicy dwuwymiarowej zawartość stosu w postaci: do elementu tablicy o
współrzędnych (x, y) zapisywany jest numer ruchu. Powstaje macierz z wypisaną kolejnością ruchów konika na szachownicy.
void wysw_pkt(int numerek, int specjal)
Wyświetla liczbę numerek w miejscu połoŜenia kursora tekstowego zaimplementowanego dzięki bibliotece ‘conio2.h’. Dodaje
ewentualne odstępy dla liczb o mniejszej ilości cyfr aby zachować spójność w wyświetlaniu macierzy(szachownicy) na ekranie.
W zaleŜności od wartości zmiennej specjal liczba pisana jest w kolorze białym dla specjal=1 lub Ŝółtym(pierwsze i ostatnie pole
trasy konika), czerwonym(pola nieodwiedzone z powodu braku rozwiązania) albo czarnym(pozostałe) dla specjal=0. Funkcja
wykorzystuje metody zmiany kolorów tekstu zawarte w bibliotece ‘conio2.h’.
void show_tab(int szach[rozmiar][rozmiar])
Wyswietla gotową szachownicę na ekranie. Wykorzystuje funkcję wysw_pkt do wyswietlania kaŜdego elementu szachownicy.
pole *ostatni(pole *pierwszy)
Po podaniu wskaźnika pierwszy na wierzchołek stosu zwraca wskaŜnik na spód stosu.
pole *poprz(pole *pierwszy, pole *od)
Zwraca wskaźnik na element stosu, którego *nast = pierwszy, czyli na element poprzedni dla pierwszy.
int main()
Funkcja podstawowa. Wykorzystuje większość z opisanych powyŜej funkcji. Jej ogólne działanie opisuje schemat blokowy:
START
Zaimplementowanie obsługi
biblioteki „conio2.h”
Wczytanie rozmiarów szachownicy i
współrzędnych początku drogi
Wyszukiwanie drogi konika i
wpisanie jej do stosu
Utworzenie dynamicznej tablicy
dwuwymiarowej i wpisanie wartości
ze stosu
Wyświetlenie wyniku
jako szachownicę i
przeglądanie kolejności
skoków
Wybór opcji w
menu
Wyświetlenie wyniku jako
lista kolejnych
współrzędnych skoków
Zwolnienie pamięci dla
stosu i tablicy
STOP
5. Instrukcja dla uŜytkownika
Uruchamiamy program. UŜytkownika wita przyjazny interfejs:
Podajemy wymiar szachownicy, musi mieścić się w przedziale <5, 19>. Następnie podajemy współrzędne pól startowych, czyli z
ktorego pola konik rozpocznie wędrówkę. Pola indeksowane są od 0, dlatego pole w górnym lewym rogu ma współrzędne (0, 0),
a pole w prawym dolnym rogu (N, N), gdzie N = wymiar szachownicy – 1. KaŜde wpisanie liczby potwierdzamy naciśnięciem
klawisza „Enter”.
Po podaniu wymiaru i współrzędnych program przez chwilę wyszukuje drogę dla konika, zapisuje ją do tablicy dynamicznej i na
końcu wyświetla wynik szukania drogi i menu:
Wybieramy jedną z dostępnych opcji w menu. Po wybraniu wyświetlenia szachownicy pojawia się na ekranie macierz ruchów
konika z zaznaczeniem pól: pierwszego i ostatniego na Ŝółto oraz ewentualnych nieodwiedzonych na czerwono:
Za pomocą klawiszy ‘<’ oraz ‘>’ (czyli ‘,’ i ‘.’) moŜemy przeglądać kolejne skoki konika na szachownicy(pole oznaczone na
biało). MoŜemy nacisnąć teŜ ‘q’ aby wrócić do menu.
Opcja menu ‘Zobaczyć stos’ wyświetla na ekranie kolejne współrzędne pól, na których stał konik szachowy:
Naciskamy dowolny klawisz, Ŝeby powrócić do menu.
JeŜeli program nie znajdzie drogi dla konika (np. dla wymiaru 7 i pola startowego (5, 4)) to tuŜ po fakcie pojawi się komunikat:
a po wybraniu w menu ‘Zobaczyć szachownicę’ ukaŜą się nieodwiedzone pola ‘0’ oznaczone na czerwono.
Aby wyjść z programu w menu naciskamy klawisz ‘q’ lub zamykamy okno systemu Windows.