diff --git a/08-bludiste/bludiste.in b/08-bludiste/bludiste.in
new file mode 100644
index 0000000000000000000000000000000000000000..d06a9a6e8b2d4aaa154936e7995c5cf8e04dc612
--- /dev/null
+++ b/08-bludiste/bludiste.in
@@ -0,0 +1,10 @@
+.##.......
+..#.####..
+$...#.....
+.####..###
+.#...0....
+.#.#######
+.#....#...
+.####..##.
+.#..##..#.
+.#......#.
diff --git a/08-bludiste/cesta.py b/08-bludiste/cesta.py
new file mode 100755
index 0000000000000000000000000000000000000000..729047f9fe411bcb687234950232a89dd69859ab
--- /dev/null
+++ b/08-bludiste/cesta.py
@@ -0,0 +1,74 @@
+#!/usr/bin/python3
+# Hledání nejkratší cesty v bludišti
+# Bludiště se načítá ze souboru "bludiste.in":
+#    "." značí volná políčka
+#    "#" jsou zdi
+#    "0" je počáteční políčko
+#    "$" je poklad, ke kterému chceme dojít
+#    "*" zapíšeme na všechna políčka nejkratší cesty
+#    "o" zapíšeme na ostatní prohledaná políčka
+
+from collections import deque
+
+class Bludiste:
+
+    def __init__(self):
+        self.bludiste = []
+        self.radku = 0
+        self.sloupcu = 0
+
+    def nacti(self, soubor):
+        with open(soubor) as f:
+            for radek in f:
+                self.bludiste.append(list(radek.strip()))
+        self.radku = len(self.bludiste)
+        self.sloupcu = len(self.bludiste[0])
+
+    def vypis(self):
+        for r in self.bludiste:
+            print("".join(r))
+
+    def najdi_start(self):
+        for r in range(self.radku):
+            for s in range(self.sloupcu):
+                if self.bludiste[r][s] == '0':
+                    return r, s
+        raise RuntimeError("Jsem ztracen: bludiště nemá začátek!")
+
+    def hledani_do_sirky(self, r, s):
+        fronta = deque()
+        fronta.append((r, s))
+        self.bludiste[r][s] = 'o'
+        self.odkud = [[None] * self.sloupcu for _ in range(self.radku)]
+        konec = False
+
+        def cesta(rr, ss):
+            while self.odkud[rr][ss] is not None:
+                rr, ss = self.odkud[rr][ss]
+                self.bludiste[rr][ss] = '*'
+
+        def soused(rr, ss):
+            if 0 <= rr < self.radku and 0 <= ss < self.sloupcu:
+                if self.bludiste[rr][ss] == '.':
+                    self.bludiste[rr][ss] = 'o'
+                    fronta.append((rr, ss))
+                    self.odkud[rr][ss] = (r, s)
+                elif self.bludiste[rr][ss] == '$':
+                    self.odkud[rr][ss] = (r, s)
+                    cesta(rr, ss)
+                    nonlocal konec
+                    konec = True
+
+        while not konec and fronta:
+            r, s = fronta.popleft()
+            soused(r-1, s)
+            soused(r+1, s)
+            soused(r, s-1)
+            soused(r, s+1)
+
+
+b = Bludiste()
+b.nacti("bludiste.in")
+r0, s0 = b.najdi_start()
+b.hledani_do_sirky(r0, s0)
+b.vypis()
diff --git a/08-bludiste/projdi.py b/08-bludiste/projdi.py
new file mode 100755
index 0000000000000000000000000000000000000000..b94e10223da4e8ec9433658703b4c26d26c4452d
--- /dev/null
+++ b/08-bludiste/projdi.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python3
+# Hledání dosažitelných políček v bludišti
+# Bludiště se načítá ze souboru "bludiste.in":
+#    "." značí volná políčka
+#    "#" jsou zdi
+#    "0" je počáteční políčko
+#    "o" zapíšeme na všechna dosažitelná políčka
+
+from collections import deque
+
+class Bludiste:
+
+    def __init__(self):
+        self.bludiste = []
+        self.radku = 0
+        self.sloupcu = 0
+
+    def nacti(self, soubor):
+        with open(soubor) as f:
+            for radek in f:
+                self.bludiste.append(list(radek.strip()))
+        self.radku = len(self.bludiste)
+        self.sloupcu = len(self.bludiste[0])
+
+    def vypis(self):
+        for r in self.bludiste:
+            print("".join(r))
+
+    def najdi_start(self):
+        for r in range(self.radku):
+            for s in range(self.sloupcu):
+                if self.bludiste[r][s] == '0':
+                    return r, s
+        raise RuntimeError("Jsem ztracen: bludiště nemá začátek!")
+
+    def hledani_do_sirky(self, r, s):
+        fronta = deque()
+        fronta.append((r, s))
+        self.bludiste[r][s] = 'o'
+
+        def soused(rr, ss):
+            if 0 <= rr < self.radku and \
+               0 <= ss < self.sloupcu and \
+               self.bludiste[rr][ss] == '.':
+                self.bludiste[rr][ss] = 'o'
+                fronta.append((rr, ss))
+
+        while fronta:
+            r, s = fronta.popleft()
+            soused(r-1, s)
+            soused(r+1, s)
+            soused(r, s-1)
+            soused(r, s+1)
+
+
+b = Bludiste()
+b.nacti("bludiste.in")
+r0, s0 = b.najdi_start()
+b.hledani_do_sirky(r0, s0)
+b.vypis()
diff --git a/08-bludiste/vzdalenosti.py b/08-bludiste/vzdalenosti.py
new file mode 100755
index 0000000000000000000000000000000000000000..3bfd65ac3dc0627d7b76b0b86509b2bf57cf46ee
--- /dev/null
+++ b/08-bludiste/vzdalenosti.py
@@ -0,0 +1,76 @@
+#!/usr/bin/python3
+# Výpočet vzdáleností v bludišti
+# Bludiště se načítá ze souboru "bludiste.in":
+#    "." značí volná políčka
+#    "#" jsou zdi
+#    "0" je počáteční políčko
+#    "o" zapíšeme na všechna dosažitelná políčka
+
+from collections import deque
+
+class Bludiste:
+
+    def __init__(self):
+        self.bludiste = []
+        self.radku = 0
+        self.sloupcu = 0
+
+    def nacti(self, soubor):
+        with open(soubor) as f:
+            for radek in f:
+                self.bludiste.append(list(radek.strip()))
+        self.radku = len(self.bludiste)
+        self.sloupcu = len(self.bludiste[0])
+
+    def vypis(self):
+        for r in self.bludiste:
+            print("".join(r))
+
+    def vypis_vzdalenost(self):
+        for r in self.vzdalenost:
+            vystup = []
+            for d in r:
+                if d is None:
+                    vystup.append("---")
+                else:
+                    vystup.append("{:3d}".format(d))
+            print(" ".join(vystup))
+
+    def najdi_start(self):
+        for r in range(self.radku):
+            for s in range(self.sloupcu):
+                if self.bludiste[r][s] == '0':
+                    return r, s
+        raise RuntimeError("Jsem ztracen: bludiště nemá začátek!")
+
+    def hledani_do_sirky(self, r, s):
+        fronta = deque()
+        fronta.append((r, s))
+        self.bludiste[r][s] = 'o'
+
+        self.vzdalenost = [[None] * self.sloupcu for _ in range(self.radku)]
+        self.vzdalenost[r][s] = 0
+
+        def soused(rr, ss, dd):
+            if 0 <= rr < self.radku and \
+               0 <= ss < self.sloupcu and \
+               self.bludiste[rr][ss] == '.':
+                self.bludiste[rr][ss] = 'o'
+                self.vzdalenost[rr][ss] = dd
+                fronta.append((rr, ss))
+
+        while fronta:
+            r, s = fronta.popleft()
+            d = self.vzdalenost[r][s]
+            soused(r-1, s, d+1)
+            soused(r+1, s, d+1)
+            soused(r, s-1, d+1)
+            soused(r, s+1, d+1)
+
+
+b = Bludiste()
+b.nacti("bludiste.in")
+r0, s0 = b.najdi_start()
+b.hledani_do_sirky(r0, s0)
+b.vypis()
+b.vypis_vzdalenost()