using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Globalization; using System.Threading; using System.Drawing; using System.Collections; namespace ConsoleApplication1 { class Vrchol { private int indexVrcholu; private int indexPredchudce; private int nejkratsiCestaZVrcholu; private Point souradnice; public int IndexVrcholu { get { return indexVrcholu; } set { indexVrcholu = value; } } public int IndexPredchudce { get { return indexPredchudce; } set { indexPredchudce = value; } } public int NejkratsiCestaZVrcholu { get { return nejkratsiCestaZVrcholu; } set { nejkratsiCestaZVrcholu = value; } } public Point Souradnice { get { return souradnice; } set { souradnice = value; } } public Vrchol(int a, int b, int c, Point p) { IndexVrcholu = a; IndexPredchudce = b; NejkratsiCestaZVrcholu = c; Souradnice = p; } public void ZapsatCestuDoMaticeSousednosti(int[][] maticeSousednosti) { try { int radek, sloupec; if (this.IndexVrcholu > this.IndexPredchudce) { radek = maticeSousednosti[0].Length - this.IndexVrcholu; sloupec = this.IndexPredchudce; } else { radek = maticeSousednosti[0].Length - this.IndexPredchudce; sloupec = this.IndexVrcholu; } maticeSousednosti[radek][sloupec] = this.NejkratsiCestaZVrcholu; } catch (Exception) { //Console.WriteLine(this.IndexVrcholu + " Chyba!"); } } } class Bludiste { //sever readonly byte sever = 1; //vychod readonly byte vychod = 2; //jih readonly byte jih = 4; //západ readonly byte zapad = 8; //konecný bod readonly byte end = 16; private byte[,] bludiste; private byte[,] bludisteObracene; private int[][] maticeSousednosti; private List vrcholy; private List hotoveVrcholy; static void Main(string[] args) { Bludiste bludiste = new Bludiste(); int r = 0; int s = 0; while (r == 0 || s == 0) { try { Console.WriteLine("Zadejte pocet radku: "); r = int.Parse(Console.ReadLine()); Console.WriteLine("Zadejte pocet sloupcu: "); s = int.Parse(Console.ReadLine()); if (r <= 0 || s <= 0) { throw new Exception(); } } catch (Exception e) { Console.WriteLine("Zadejte nenulovou, kladnou hodnotu."); } } bludiste.inicializuj(r, s); bludiste.Generuj(); bludiste.vypisBludiste(); Console.WriteLine(); } /*******IMPROVING*****/ private void ZapsatKrizovatkuDoBludiste(Vrchol v) { if (v.IndexPredchudce >= 0) { int x1, x2, y1, y2; x1 = v.Souradnice.X; x2 = IndexNaSouradnice(v.IndexPredchudce).X; y1 = v.Souradnice.Y; y2 = IndexNaSouradnice(v.IndexPredchudce).Y; if (x1 == x2) { if (y1 > y2) { bludiste[x1, y1] |= zapad; bludiste[x2, y2] |= vychod; } else { bludiste[x1, y1] |= vychod; bludiste[x2, y2] |= zapad; } } if (y1 == y2) { if (x1 > x2) { bludiste[x1, y1] |= sever; bludiste[x2, y2] |= jih; } else { bludiste[x1, y1] |= jih; bludiste[x2, y2] |= sever; } } } } private void Generuj() { while (vrcholy.Count != 0) { Vrchol min = null; if ((min = GetMinCestu()) != null) { PridejSousedyDoPole(min); DeleteVrchol(min.IndexVrcholu); min.ZapsatCestuDoMaticeSousednosti(maticeSousednosti); ZapsatKrizovatkuDoBludiste(min); VypisVrcholyVPoli(); } } } private Point IndexNaSouradnice(int index) { return new Point(index/bludiste.GetLength(1), index%bludiste.GetLength(1)); } private int SouradniceNaIndex(Point souradnice) { return souradnice.X * bludiste.GetLength(1) + souradnice.Y; } public bool VrcholJeHotovy(int index) { if (hotoveVrcholy.Contains(index)) { return true; } else return false; } private void PridejSousedyDoPole(Vrchol vrchol) { Random r = new Random(); Vrchol sever = new Vrchol(vrchol.IndexVrcholu - bludiste.GetLength(1), vrchol.IndexVrcholu, r.Next(1, 100), new Point(vrchol.Souradnice.X - 1, vrchol.Souradnice.Y)); r = new Random(); Vrchol vychod = new Vrchol(vrchol.IndexVrcholu + 1, vrchol.IndexVrcholu, r.Next(1, 100), new Point(vrchol.Souradnice.X, vrchol.Souradnice.Y + 1)); r = new Random(); Vrchol jih = new Vrchol(vrchol.IndexVrcholu + bludiste.GetLength(1), vrchol.IndexVrcholu, r.Next(1, 100), new Point(vrchol.Souradnice.X + 1, vrchol.Souradnice.Y)); r = new Random(); Vrchol zapad = new Vrchol(vrchol.IndexVrcholu - 1, vrchol.IndexVrcholu, r.Next(1, 100), new Point(vrchol.Souradnice.X, vrchol.Souradnice.Y - 1)); PridejVrchol(sever); PridejVrchol(vychod); PridejVrchol(jih); PridejVrchol(zapad); } private bool JeHranaVMatici(Vrchol v) { try { int radek, sloupec; if (v.IndexVrcholu > v.IndexPredchudce) { radek = maticeSousednosti[0].Length - v.IndexVrcholu; sloupec = v.IndexPredchudce; } else { radek = maticeSousednosti[0].Length - v.IndexPredchudce; sloupec = v.IndexVrcholu; } if (maticeSousednosti[radek][sloupec] == 0) { return false; } else return true; } catch (IndexOutOfRangeException) { return false; } } private void VypisVrcholyVPoli() { Console.WriteLine("I P D X Y"); Console.WriteLine("-----------"); foreach (Vrchol v in vrcholy) { Console.WriteLine(v.IndexVrcholu + " " + v.IndexPredchudce + " " + v.NejkratsiCestaZVrcholu + " " + v.Souradnice.X + " " + v.Souradnice.Y); } Console.WriteLine(); } private bool VrcholJeOK(Vrchol vrchol) { int pocetRadku = bludiste.GetLength(0); int pocetSloupcu = bludiste.GetLength(1); if (vrchol.IndexVrcholu >= 0 && vrchol.IndexVrcholu < pocetRadku * pocetSloupcu && vrchol.Souradnice.X >= 0 && vrchol.Souradnice.X < pocetRadku && vrchol.Souradnice.Y >= 0 && vrchol.Souradnice.Y < pocetSloupcu) { return true; } else { return false; } } private Vrchol VrcholJeVPoli(Vrchol vrchol) { foreach (Vrchol v in vrcholy) { if (vrchol.IndexVrcholu == v.IndexVrcholu) { return v; } } return null; } private Vrchol VrcholJeVPoli(int indexVrcholu) { foreach (Vrchol v in vrcholy) { if (v.IndexVrcholu == indexVrcholu) { return v; } } return null; } private void PridejVrchol(Vrchol vrchol) { Vrchol pom = VrcholJeVPoli(vrchol); if (!VrcholJeHotovy(vrchol.IndexVrcholu)) { if (pom != null && vrchol.NejkratsiCestaZVrcholu < pom.NejkratsiCestaZVrcholu) { if (VrcholJeOK(vrchol)) { DeleteVrchol(pom.IndexVrcholu); vrcholy.Add(vrchol); } } else if (pom == null) { if (VrcholJeOK(vrchol)) vrcholy.Add(vrchol); } } } private Vrchol GetMinCestu() { Vrchol pom = null; int min = int.MaxValue; foreach (Vrchol v in vrcholy) { if (v.NejkratsiCestaZVrcholu < min) { min = v.NejkratsiCestaZVrcholu; pom = v; } } return pom; } private void DeleteVrchol(int indexVrcholu) { foreach (Vrchol v in vrcholy) { if (v.IndexVrcholu == indexVrcholu) { vrcholy.Remove(v); hotoveVrcholy.Add(v.IndexVrcholu); break; } } } /*********************/ private void inicializuj(int rad, int sl) { //inicializace bludeiste bludiste = new byte[rad, sl]; bludisteObracene = new byte[rad, sl]; for (int r = 0; r < bludiste.GetLength(0); r++) { for (int s = 0; s < bludiste.GetLength(1); s++) { bludiste[r, s] = 0; bludisteObracene[r, s] = 0; } } //inicializace matice sousednosti pro uchování tvrdosti skály int pocet = rad * sl - 1; maticeSousednosti = new int[pocet][]; for (int r = 0, sPocet = pocet; r < pocet; r++, sPocet--) { maticeSousednosti[r] = new int[sPocet]; } vrcholy = new List(); Vrchol start = new Vrchol((bludiste.GetLength(0) - 1) * bludiste.GetLength(1), -1, 0, new Point(bludiste.GetLength(0) - 1, 0)); vrcholy.Add(start); hotoveVrcholy = new List(); } private int nastavTvrdostSkaly(int x, int y, int tvrdost, int bludisteX, int bludisteY) { try { if (x < 0 || y < 0) { throw new IndexOutOfRangeException(); } if (bludiste[bludisteX, bludisteY] != 0) { return -1; } int radek = x > y ? y : x; int sloupec = maticeSousednosti[0].Length - (x > y ? x : y) - 1; if (maticeSousednosti[radek][sloupec] != 0) { return maticeSousednosti[radek][sloupec]; } maticeSousednosti[radek][sloupec] = tvrdost; return tvrdost; } catch (IndexOutOfRangeException) { return -1; } } private int getIndexBludiste(int radIndex, int slIndex) { try { //pokud je index mimo rozsah, vyvolá vyjímku bludiste[radIndex, slIndex] = bludiste[radIndex, slIndex]; return bludiste.GetLength(1) * radIndex + slIndex; } catch (IndexOutOfRangeException e) { return -1; } } private void vypisBludiste() { Console.WriteLine(); for (int s = 0; s < bludiste.GetLength(1); s++) { Console.Write(" _"); } Console.WriteLine(); for (int r = 0; r < bludiste.GetLength(0); r++) { for (int s = 0; s < bludiste.GetLength(1); s++) { StringBuilder ch = new StringBuilder(); if (((bludiste[r, s] & zapad) == zapad) || ((s - 1) >= 0 && (bludiste[r, s - 1] & vychod) == vychod)) { ch.Append(" "); } else { ch.Append("|"); } if (((bludiste[r, s] & jih) == jih) || ((r + 1) < bludiste.GetLength(0) && (bludiste[r + 1, s] & sever) == sever) || (r == (bludiste.GetLength(0) - 1) && s == 0)) { ch.Append(" "); } else { ch.Append("_"); } Console.Write(String.Format("{0}", ch)); } Console.Write("|"); Console.WriteLine(); } } private void vypisMaticiSousednosti() { for (int i = 0; i < maticeSousednosti.Length; i++) { for (int j = 0; j < maticeSousednosti[i].Length; j++) { Console.Write(maticeSousednosti[i][j] + " "); } Console.WriteLine(); } } private void generujBludiste() { Random r = new Random(); int sl = 0; int rad = bludiste.GetLength(0) - 1; int rndMin = 1; int rndMax = 100; bool smer = true; int pocetPruchodu = 1; //sousedni hrany: 0 = north, 1 = east, 2 = south, 3 = west int[] sousedniHrany = new int[4]; while (true) { if (smer == false && sl == 0 && rad == (bludiste.GetLength(0) - 1)) { break; } //spočítej tvrdost sousedních stěn //pokud byly stěny již vygenerovány, nebo neexistují (okraj bludiště), je jejich hodnota rovna -1 sousedniHrany[0] = nastavTvrdostSkaly(getIndexBludiste(rad, sl), getIndexBludiste(rad - 1, sl), r.Next(rndMin, rndMax), rad - 1, sl); sousedniHrany[1] = nastavTvrdostSkaly(getIndexBludiste(rad, sl), getIndexBludiste(rad, sl + 1), r.Next(rndMin, rndMax), rad, sl + 1); sousedniHrany[2] = nastavTvrdostSkaly(getIndexBludiste(rad, sl), getIndexBludiste(rad + 1, sl), r.Next(rndMin, rndMax), rad + 1, sl); sousedniHrany[3] = nastavTvrdostSkaly(getIndexBludiste(rad, sl), getIndexBludiste(rad, sl - 1), r.Next(rndMin, rndMax), rad, sl - 1); //nalezení minimální tvrdosti int min = int.MaxValue; int minIndex = -1; for (int i = 0; i < sousedniHrany.Length; i++) { if (sousedniHrany[i] < min && sousedniHrany[i] != -1) { min = sousedniHrany[i]; minIndex = i; } } //pokud neexistuje další hrana, změň směr a vracej se cestou zpět if (minIndex == -1) { if (smer == true) { bludiste[rad, sl] = end; Console.WriteLine("Stav po {0}. pruchodu", pocetPruchodu); this.vypisBludiste(); Console.WriteLine(); pocetPruchodu++; } switch (bludisteObracene[rad, sl]) { case 1: rad -= 1; break; case 2: sl += 1; break; case 4: rad += 1; break; case 8: sl -= 1; break; default: break; } smer = false; continue; } //existuje stěna, pro nastav směr a nastav pozici pro další průchod smer = true; //minIndex: 0 = north, 1 = east, 2 = south, 3 = west //bludiste: b0001 = north, b0010 = east, b0100 = south, b1000 = west switch (minIndex) { case 0: bludiste[rad, sl] |= sever; rad -= 1; bludisteObracene[rad, sl] = jih; break; case 1: bludiste[rad, sl] |= vychod; sl += 1; bludisteObracene[rad, sl] = zapad; break; case 2: bludiste[rad, sl] |= jih; rad += 1; bludisteObracene[rad, sl] = sever; break; case 3: bludiste[rad, sl] |= zapad; sl -= 1; bludisteObracene[rad, sl] = vychod; break; default: break; } } } } }