-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.hs
86 lines (67 loc) · 2.37 KB
/
main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import System.Random
type Board = [[Char]]
type Point = (Int, Int)
fillChar = '█'
emptyChar = ' '
generateEmptyBoard :: Int -> Int -> [[Char]]
generateEmptyBoard w h = take w $ repeat $ take h $ repeat emptyChar
board :: Board
board = insertAtStart (generateEmptyBoard 15 15) fillChar
insertAtStart :: [[Char]] -> Char -> [[Char]]
insertAtStart (b:bs) val = (replaceAt 0 fillChar b : bs)
startPoint :: Point
startPoint = (0, 0)
getPoint :: Board -> Point -> Char
getPoint b (row, col)
| isInsideBounds b (row, col) == False = fillChar
| otherwise = b !! col !! row
isAvailable :: Board -> Point -> Bool
isAvailable b p = (== ' ') $ getPoint b p
getAvailableTiles :: Board -> Point -> [Point]
getAvailableTiles b (row, col) =
filter (isAvailable b) $
filter (isInsideBounds b) $
[(row - 2, col), (row + 2, col), (row, col - 2), (row, col + 2)]
getPath :: Point -> Point -> [Point]
getPath (x1, y1) (x2, y2)
| x1 == x2 && y1 < y2 = [(x2, y2 - 1)] ++ [(x2, y2)]
| x1 == x2 && y1 > y2 = [(x2, y2 + 1)] ++ [(x2, y2)]
| y1 == y2 && x1 < x2 = [(x2 - 1, y2)] ++ [(x2, y2)]
| y1 == y2 && x1 > x2 = [(x2 + 1, y2)] ++ [(x2, y2)]
replaceAt :: Int -> a -> [a] -> [a]
replaceAt z y xs = as ++ (y : tail bs)
where
(as, bs) = splitAt z xs
insertPoints :: Board -> [Point] -> Board
insertPoints board [] = board
insertPoints board ((x, y):ps) = insertPoints newBoard ps
where
newRow = replaceAt x fillChar $ board !! y
newBoard = replaceAt y newRow board
pickPoint :: RandomGen g => g -> [Point] -> (Point, g)
pickPoint g ps = (ps !! x, newG)
where
(x, newG) = randomR (min, max) g
min = 0
max = (length ps) - 1
isInsideBounds :: Board -> Point -> Bool
isInsideBounds board (x, y)
| x < 0 = False
| x > (length (head board) - 1) = False
| y < 0 = False
| y > ((length board) - 1) = False
| otherwise = True
buildMaze board [] _ = board
buildMaze board (cP:restPoints) gen
| length (getAvailableTiles board cP) == 0 = buildMaze board restPoints gen
| otherwise =
let availTiles = getAvailableTiles board cP
(nextPoint, newGen) = pickPoint gen $ availTiles
newBoard = insertPoints board $ getPath cP nextPoint
in buildMaze newBoard (nextPoint : cP : restPoints) newGen
printMaze :: Board -> IO ()
printMaze = putStr . unlines
main :: IO ()
main = do
seed <- getStdGen
printMaze $ buildMaze (generateEmptyBoard 32 32) [startPoint] seed