main2.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #include <iostream>
  2. #include <fstream> // do wczytywania pliku
  3. #include <algorithm> // do usuwania ostatniego wyszukanego elementu z listy otwartej (erase)
  4. #include <vector> // do dynamicznych list (lista w które możemy zmieniać, dodawać/usuwać elementy)
  5. #include <math.h> // do sqrt i pow
  6. using namespace std;
  7. class Punkt {
  8. private:
  9. int sciezka; // do wyznaczenia ścieżki
  10. float funkcjaG = 0; //
  11. float funkcjaF = 0; //
  12. int x; //współrzędna x na mapie
  13. int y; //współrzędna y na mapie
  14. Punkt* rodzic = NULL; // rodzic punktu, na początku null ponieważ nie wiemy jaki jest rodzic
  15. public:
  16. void setX(int x) { //ustawia wartość x
  17. this->x = x;
  18. }
  19. void setY(int y) { //ustawia wartość y
  20. this->y = y;
  21. }
  22. void setSciezka(int sciezka) { //ustawia wartosc ścieżki
  23. this->sciezka = sciezka;
  24. }
  25. void setFunkcjaF(int funkcjaF) { //ustawia wartość funkcji F
  26. this->funkcjaF = funkcjaF;
  27. }
  28. void setRodzic(Punkt* rodzic) { //ustawia wartość rodzica
  29. this->rodzic = rodzic;
  30. }
  31. int getX() { //zwraca wartość x
  32. return this->x;
  33. }
  34. int getY() { //zwraca wartość y
  35. return this->y;
  36. }
  37. int getSciezka() { //zwraca wartość ścieżki
  38. return this->sciezka;
  39. }
  40. float getFunkcjaF() { //zwraca wartość funkcji F
  41. return this->funkcjaF;
  42. }
  43. float getFunkcjaG() { //zwraca wartość funkcji G
  44. return this->funkcjaG;
  45. }
  46. Punkt* getRodzic() { //zwraca wartość rodzica
  47. return this->rodzic;
  48. }
  49. //oblicza koszt dotarcia i przypisuje go do obiektu, wykorzystana przy wysuzkiwaniu sąsiednich punktów
  50. //ustawia wartość funkcji f i g, oblicza wartość funkcji h (heurystyki)
  51. void ObliczanieFunkcji(Punkt* celPunkt) {
  52. float funkcjaH = sqrt(pow((this->x - celPunkt->x), 2) + pow((this->y - celPunkt->y), 2));
  53. this->funkcjaG = this->rodzic->funkcjaG + 1;
  54. this->funkcjaF = funkcjaH + this -> funkcjaG;
  55. }
  56. //sprawdza czy dotarto do końca (destination)
  57. bool dotarcieDoCelu(Punkt* destination) {
  58. if (this == destination) { //jeśli obecny punkt jest taki sam jak końcowy
  59. // zaznacza ściężkę mapie za pomocą jedynek, dopóki rodzic nie jest pusty (null)
  60. while (destination->getRodzic()) { //dopóki mamy rodzica while wywołuje się
  61. destination->setSciezka(7); //ustawia ścieżkę na 1
  62. destination = destination->getRodzic(); //pobiera rodzica końca //rodzic punktu końcowego staje się punktem końcowym, wraca po rodzicach ustawiając na 1 wartość punktów, wyznaczając tym samym ścieżkę
  63. }
  64. return true;
  65. }
  66. return false;
  67. }
  68. //sprawdza czy obiekt znajduje się w liście (wektorze) do sprawdzania listy otwartej i zamkniętej
  69. bool sprawdzenieListy(vector<Punkt*> lista) {
  70. for (auto elementListy : lista) //auto przeiterowuje się przez listę, typ iteratora ustawia się sam
  71. if (elementListy == this) return true;
  72. return false;
  73. }
  74. };
  75. int wys = 20, szer = 20;
  76. //wektor rozmiaru szerokości, zawiera elementy wartości vector<Punkt>(wys)
  77. vector<vector<Punkt>> siatka(szer, vector<Punkt>(wys));
  78. // wektor przechowujący wskaźniki na klasę Punkt
  79. vector<Punkt*> Lista_Otwarta; //lista otwarta
  80. vector<Punkt*> Lista_Zamknieta; //lista zamknięta
  81. //funckja porównuje wartości funkcji F i jeśli znajdzie namniejszy to zamienia go, jeśli mamy kilka takich samych wartości funkcji F to brany jest ostatni element (ponieważ jako ostatni "przeszedł" przez pętle for)
  82. Punkt* najmniejszaFunkcjaF() {
  83. Punkt* wartoscMinimum = Lista_Otwarta[0];
  84. for (auto elementListy : Lista_Otwarta)
  85. if (elementListy->getFunkcjaF() <= wartoscMinimum->getFunkcjaF()) wartoscMinimum = elementListy;
  86. return wartoscMinimum;
  87. }
  88. vector<Punkt*> znajdzSasiednie(Punkt* sprawdzanyPunkt) { //Wyznacza sąsiadów sprawdzanego punktu //sprawdzanyPunkt - punkt w którym aktualnie się znajdujemy
  89. // wektor wskaznikow na klasę Punkt o wielkości 4 z default wartościami null
  90. vector<Punkt*> sasiednie(4, NULL);
  91. cout << "sasiednie do [" << sprawdzanyPunkt->getX() << "," << sprawdzanyPunkt->getY() << "]:" << endl;
  92. // znajduje sasiednie punktu jeżeli ich współrzędne nie są większe niż mapa
  93. ///////////////////////////////////////////////////////////////////////////
  94. /// kolejność indeksów w sasiednie[] odpowiada hierarchii ruchu
  95. // dół
  96. if (sprawdzanyPunkt->getY() + 1 < wys) { // sprawdza czy sąsiad nie wypada poza mapę na dole
  97. cout << "z dolu [" << sprawdzanyPunkt->getX() << "," << sprawdzanyPunkt->getY() + 1 << "]" << endl;
  98. sasiednie[0] = &siatka[sprawdzanyPunkt->getX()][sprawdzanyPunkt->getY() + 1]; //nadpisujemy wartość NULL adresem punktu na siatce o współrzędnych x i y
  99. }
  100. // lewo
  101. if (sprawdzanyPunkt->getX() - 1 >= 0){ // sprawdza czy sąsiad nie wypada poza mapę na lewo
  102. cout << "z lewej [" << sprawdzanyPunkt->getX() - 1 << "," << sprawdzanyPunkt->getY() << "]" << endl;
  103. sasiednie[1] = &siatka[sprawdzanyPunkt->getX() - 1][sprawdzanyPunkt->getY()];
  104. }
  105. // góra
  106. if (sprawdzanyPunkt->getY() - 1 >= 0){ // sprawdza czy sąsiad nie wypada poza mapę na górze
  107. cout << "z gory [" << sprawdzanyPunkt->getX() << "," << sprawdzanyPunkt->getY() -1 << "]" << endl;
  108. sasiednie[2] = &siatka[sprawdzanyPunkt->getX()][sprawdzanyPunkt->getY() - 1];
  109. }
  110. // prawo
  111. if (sprawdzanyPunkt->getX() + 1 < szer){ // sprawdza czy sąsiad nie wypada poza mapę na prawo
  112. cout << "z prawej [" << sprawdzanyPunkt->getX() + 1 << "," << sprawdzanyPunkt->getY() << "]" << endl;
  113. sasiednie[3] = &siatka[sprawdzanyPunkt->getX() + 1][sprawdzanyPunkt->getY()];
  114. }
  115. return sasiednie;
  116. }
  117. bool a_star(int xPoczatek, int yPoczatek, int xKoniec, int yKoniec) {
  118. Punkt* poczatek = &siatka[xPoczatek][yPoczatek];
  119. Punkt* koniec = &siatka[xKoniec][yKoniec];
  120. Lista_Otwarta.push_back(poczatek); //punkt początkowy trafia na listę otwartą
  121. while (Lista_Otwarta.size() > 0) { //dopóki lista otwarta zawiera choć jeden element //jeśli np. punkt cel będzie odgrodzony scianami, wszystkie możliwe punkty będą trafiać systematycznie do list otwartych, 1 element z najmniejszą wartością funkcji f zostanie usunięty z listy otwartej i trafi na listę zamkniętą //powtarzając ten proces aż do wyczerpania punktów z wartością scieżki równą zero, lista otwarta się wyczerpie, algorytm zwróci false
  122. Punkt* sprawdzanyPunkt = najmniejszaFunkcjaF(); //zmienna wskazuję na wartość punktu z najmniejszą wartością funkcji F
  123. cout << "sprawdzamy [" << sprawdzanyPunkt->getX() << "," << sprawdzanyPunkt->getY() << "]" << endl;
  124. //czy sprawdzany Punkt jest końcem trasy
  125. if (sprawdzanyPunkt->dotarcieDoCelu(koniec)) {
  126. poczatek->setSciezka(7);
  127. return true;
  128. }
  129. cout << "[" << sprawdzanyPunkt->getX() << "," << sprawdzanyPunkt->getY() << "] wpisujemy na liste zamknieta" << endl;
  130. Lista_Otwarta.erase(std::remove(Lista_Otwarta.begin(), Lista_Otwarta.end(), sprawdzanyPunkt), Lista_Otwarta.end()); //listaOtwarta.begin() poczaek listy, listaOtwarta.end() koniec listy, rozwana Punkt to element który chcemy usunąć //erase wyszkuje między podanym zakresem, podaną wartośc i usuwa ją
  131. Lista_Zamknieta.push_back(sprawdzanyPunkt); //dopisuje element na końcu listy
  132. // wektor przechowujący wskazniki na klasę Punkt
  133. vector<Punkt*> sasiedniPunkt = znajdzSasiednie(sprawdzanyPunkt);
  134. for (auto elementListy : sasiedniPunkt) {
  135. //jeśli element jest nullem, lub 5 (ściąną) lub jest na liście zamkniętęj to: akutalana "iteracja" for'a jest pomijana
  136. if (elementListy->sprawdzenieListy(Lista_Zamknieta) || elementListy == NULL || elementListy->getSciezka() == 5) //elkement lsty jest w tym przypadku sąsiadem
  137. continue;
  138. if (sprawdzanyPunkt->getFunkcjaG()+1 < elementListy->getFunkcjaG() || !elementListy->sprawdzenieListy(Lista_Otwarta)) { //if spełnia się jeżeli wartosc funkcji g sąsiada jest większa od wartości funkcji g sprawdzanego punktu lub gdy sąsiad nie znajduje się na liście otwartej
  139. elementListy->setRodzic(sprawdzanyPunkt); //rodzicem zostaje sprawdzony Punkt
  140. elementListy->ObliczanieFunkcji(koniec); //oblicznie funkcji dla punkty końcowego (meta)
  141. cout << "[" << sprawdzanyPunkt->getX() << "," << sprawdzanyPunkt->getY() << "] zostaje rodzicem [" << elementListy->getX() << "," << elementListy->getY() << "]" << endl;
  142. if (!elementListy->sprawdzenieListy(Lista_Otwarta)) { //ponownie sprawdzamy czy sąsiedni punkt nie jest na liście otwartej, ponieważ poprzedni if mógł zostać spełniony innym warunkiem //wykrzyknik oznacza negację warunku
  143. cout << "[" << elementListy->getX() << "," << elementListy->getY() << "] wpisujemy na liste otwarta" << endl;
  144. Lista_Otwarta.push_back(elementListy); //wpisujemy na listę otwartą
  145. }
  146. }
  147. }
  148. }
  149. return false;
  150. }
  151. void wyswietlMape() { //wyswietla mapę
  152. for (int x = 0; x < wys; x++) {
  153. for (int y = 0; y < szer; y++)
  154. cout << siatka[y][x].getSciezka() << " ";
  155. cout << endl;
  156. }
  157. }
  158. void loadFile(string name) {
  159. ifstream file(name);
  160. char temp;
  161. for (int y = 0; y < wys; y++) {
  162. for (int x = 0; x < szer; x++) {
  163. file >> temp;
  164. siatka[x][y].setX(x);
  165. siatka[x][y].setY(y);
  166. siatka[x][y].setSciezka(temp - '0');
  167. }
  168. }
  169. file.close();
  170. }
  171. int main() {
  172. loadFile("grid.txt");
  173. // funkcja aGwiazdka zwraca wartość bool, jeśli true
  174. a_star(0, 19, 19, 0) ? cout << "sciezka wyznaczona :)" << endl : cout << "scieżka nie wyznaczona :(" << endl; //skrócony if else, za pytajnikiem zostanie zwrócowny w przypadku true, za dwukropkiem w przypadku false
  175. wyswietlMape();
  176. return 0;
  177. }
  178. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  179. /////////////////////////////////////////////////////////////////////////// KOLEJNOŚĆ KROKÓW ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  180. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////