/*************************************************************/ public static Graph generirajGraph(char[][] lavirint) { // Od lavirintot sozdavame graf na sledniov nacin: // 1. Sekoe pole od lavirintot go pretstavuvame so jazel vo grafot // 2. Dokolku nema prepreka pomegju 2 polinja, togas dodavame rebro pomegju nivnite soodvetni jazli vo grafot // 3. Dokolku nema prepreka pomegju 2 polinja, togas NE dodavame rebro pomegju soodvetnite jazli vo grafot // 4. Grafot e ORIENTIRAN, so ogled na toa deka ako postoi pat pomegju 2 sosedni polinja, togas dodavame rebra i vo dvete nasoki, // bidejki ne postoi ogranicuvanje za nasokata vo koja smeeme da se dvizime // Algoritam za naogjanje resenie: // 1. DFS: pocetna sostojva: START, celnaSostojba: EXIT (soodvetnite jazli vo grafot) koordinati = new EdgeList(); polinja = new EdgeList(); int brojPolinja = lavirint.Length; int[] dx = new int[] { 0, 1, 0, -1 }; // Offset za x-oska: Gore, Desno, Dole, Levo int[] dy = new int[] { 1, 0, -1, 0 }; // Offset za y-oska: Gore, Desno, Dole, Levo Graph g = new Graph(brojPolinja * brojPolinja); // Mapiranje na sekoj par koordinati od matricata vo soodveten id na jazel, i obratno int jazelId = 0; for (int i = 0; i < brojPolinja; i++) { for (int j = 0; j < brojPolinja; j++) { koordinati.put(kodirajKoordinati(i, j), jazelId); polinja.put(jazelId, kodirajKoordinati(i, j)); jazelId++; } } // Nadvoresnata ramka e celosen dzid (ograda), osven START i EXIT, pa zatoa ke pocneme od indeks lavirint[1][1] for (int i = 1; i < brojPolinja - 1; i++) { for (int j = 1; j < brojPolinja - 1; j++) { if (lavirint[i][j] != '#') { //ako poleto e pristapno... int jazelID = koordinati.get(kodirajKoordinati(i, j)); for (int k = 0; k < 4; k++) { int iSosed = i + dy[k]; int jSosed = j + dx[k]; if (lavirint[iSosed][jSosed] == 'S') { start = koordinati.get(kodirajKoordinati(iSosed, jSosed)); } if (lavirint[iSosed][jSosed] == 'E') { exit = koordinati.get(kodirajKoordinati(iSosed, jSosed)); } // Ako moze da se premine od segasnoto pole do sosednoto, a ako sosedot e #, togas ne dodavame rebro if (lavirint[iSosed][jSosed] == 'S' || lavirint[iSosed][jSosed] == 'E' || lavirint[iSosed][jSosed] == ' ') { int sosedID = koordinati.get(kodirajKoordinati(iSosed, jSosed)); g.dodadiRebro_Directed(jazelID, sosedID); g.dodadiRebro_Directed(sosedID, jazelID); } } } } } return(g); }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // GENERIRANJE NA SLUCAEN LAVIRINT /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* Generiranje na proizvolen lavirint so randomiziran DFS */ public static char[][] generirajLavirint(int N) { char[][] lavirint = new char[2 * N + 1][]; for (int i = 0; i < (2 * N + 1); i++) { lavirint[i] = new char[2 * N + 1]; } for (int i = 0; i < 2 * N + 1; i++) { for (int j = 0; j < 2 * N + 1; j++) { lavirint[i][j] = ' '; } } // Na pocetokot lavirintot e celiot so dzidovi, nema nitu eden pat for (int i = 0; i < 2 * N + 1; i += 2) { for (int j = 0; j < 2 * N + 1; j++) { lavirint[i][j] = '#'; lavirint[j][i] = '#'; } } Graph g = new Graph(N * N); Random r = new Random(); EdgeList indeksi = new EdgeList(); EdgeList pol = new EdgeList(); int C = 0; //Offset za Gore, Desno, Dole, Levo int[] dx = new int[] { 0, 2, 0, -2 }; int[] dy = new int[] { -2, 0, 2, 0 }; //Stavanje na koordinatite na lavirintot vo EdgeLista for (int i = 1; i < 2 * N; i += 2) { for (int j = 1; j < 2 * N; j += 2) { indeksi.put(kodirajKoordinati(i, j), C); pol.put(C, kodirajKoordinati(i, j)); C++; } } for (int i = 1; i < 2 * N; i += 2) { for (int j = 1; j < 2 * N; j += 2) { for (int k = 0; k < 4; k++) { int ito = i + dy[k], jto = j + dx[k]; if (!(ito == -1 || jto == -1 || ito >= 2 * N || jto >= 2 * N)) { g.dodadiRebro(indeksi.get(kodirajKoordinati(i, j)), indeksi.get(kodirajKoordinati(ito, jto))); } } } } // Vo prvata iteracija pravime eden DFS (slednata sostojba se izbira slucajno) od teminja koi gi oznacuvame S i E (start & end) // So ova obezbeduvame deka lavirintot ke ima resenie // DFS e randomiziran, t.e odbira eden neposeten sosed na SLUCAEN NACIN // Potoa pustame uste 2 DFS od slucajni pozicii vo lavirintot za da otstranime del od preprekite, da ima povekje patista for (int brojac = 0; brojac < 2; brojac++) { int inn = -1, jn = -1, startSostojba, celnaSostojba; if (brojac == 0) { int strana = abs(r.Next()) % 2; int iStart, jStart, iEnd, jEnd; if (strana == 1) { iStart = 1 + abs(r.Next()) % (2 * N - 1); jStart = 1; iEnd = 1 + abs(r.Next()) % (2 * N - 1); jEnd = 2 * N - 1; if (lavirint[iStart][jStart] == '#') { iStart++; } if (lavirint[iEnd][jEnd] == '#') { iEnd++; } } else { iStart = 1; jStart = 1 + abs(r.Next()) % (2 * N - 1); iEnd = 2 * N - 1; jEnd = 1 + abs(r.Next()) % (2 * N - 1); if (lavirint[iStart][jStart] == '#') { jStart++; } if (lavirint[iEnd][jEnd] == '#') { jEnd++; } } lavirint[iStart][jStart] = 'S'; lavirint[iEnd][jEnd] = 'E'; startSostojba = indeksi.get(kodirajKoordinati(iStart, jStart)); celnaSostojba = indeksi.get(kodirajKoordinati(iEnd, jEnd)); } else { startSostojba = abs(r.Next()) % N; celnaSostojba = (2 * N - 2) * (2 * N - 2) + abs(r.Next()) % (N * N - (2 * N - 2) * (2 * N - 2)); } Stack <int> s = new Stack <int>(); bool[] visited = new bool[N * N]; s.Push(startSostojba); visited[startSostojba] = true; while (s.Count != 0) { int v = s.Peek(); if (v == celnaSostojba) { break; } char[] delimiters = new char[] { ' ' }; string[] br = pol.get(v).Split(delimiters); int vi = int.Parse(br[0]), vj = int.Parse(br[1]), obidi = 0, rand = -1; bool imaNeposetenSosed = false; while (!imaNeposetenSosed && obidi < 10) { rand = abs(r.Next()) % 4; inn = vi + dy[rand]; jn = vj + dx[rand]; obidi++; if (!(jn <= 0 || inn <= 0 || inn >= 2 * N || jn >= 2 * N)) { if (!visited[indeksi.get(kodirajKoordinati(inn, jn))]) { imaNeposetenSosed = true; } } } if (imaNeposetenSosed) { int next = indeksi.get(kodirajKoordinati(inn, jn)); s.Push(next); visited[next] = true; // Se probivame niz preprekite i gi otstranuvame if (rand == 0) { lavirint[inn + 1][jn] = ' '; } else if (rand == 1) { lavirint[inn][jn - 1] = ' '; } else if (rand == 2) { lavirint[inn - 1][jn] = ' '; } else if (rand == 3) { lavirint[inn][jn + 1] = ' '; } } else { s.Pop(); } } } return(lavirint); }