| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 | -- Mine Sweeper Lab-- Import sectionimport Data.Charimport Data.Set ( Set )import qualified Data.Set as Simport Data.Universe.Helpers ( cartesianProduct ) -- Need to be installed : `cabal install universe`import Data.List ( foldl1' )-- Typesdata Cell   = Covered Int Bool Bool -- number of bombs around ; has bomb ; has flag            | Uncovered Int -- number of bombs around            | Selecteddata Grid = Grid [[Cell]]data StdGen = SG -- TODO : replacetype Mat = [[Int]]-- Methodsinstance Show Cell where    show ( Covered _ _ hasFlag ) = if hasFlag then "[F]" else "[ ]"    show ( Uncovered n ) = ['(', intToDigit n, ')']    show Selected = ">x<"instance Show Grid where    show (Grid a) = unlines $ map (unwords . map show) a-- FunctionsrandSet::Int -> StdGen -> StdGen -> Int -> Int -> Set (Int, Int)randSet n sg1 sg2 h w =     let byl = randomRs (0, h - 1) sg1 in    let bxl = randomRs (0, w - 1) sg2 in    let bl = zip byl bxl in    let biggerSets = scanl (flip S.insert) S.empty bl in    head (dropWhile (\s -> S.size s < n) biggerSets)grid::Int -> Int -> Set (Int, Int) -> Gridgrid h w s = Grid [ [Covered 0 (S.member (y, x) s) False | x <- [0..w-1] ] | y <- [0..h-1] ]randomRs (x, y) sg = [x + mod k (y - x) | k <- [1..y] ] -- TODO : replacemineIndic::Cell -> IntmineIndic c = let Covered _ b _ = c in if b then 1 else 0mines::Grid -> Matmines g = let Grid m = g in map (map mineIndic) mmoveUp::Mat -> MatmoveUp m = concat [tail m, [[0 | _ <- [1..length (m!!0)]]]]moveDown::Mat -> MatmoveDown m = concat [[[0 | _ <- [1..length (m!!0)]]], init m]moveRight::Mat -> MatmoveRight m = map (\l -> 0 : init l) mmoveLeft::Mat -> MatmoveLeft m = map (\l -> concat [tail l, [0]]) mgridMoves::Mat -> [Mat]gridMoves m =    let hMov = [id, moveUp, moveDown] in    let wMov = [id, moveLeft, moveRight] in    let allMov = tail $ cartesianProduct (.) hMov wMov in    map (\f -> f m) allMovmatrixSum::Mat -> Mat -> MatmatrixSum m1 m2 = zipWith (zipWith (+)) m1 m2neighbourMap::Grid -> MatneighbourMap g =    let Grid cm = g in    let m = map (map mineIndic) cm in    foldl1' matrixSum (gridMoves m)updateCell::Cell -> Int -> CellupdateCell c n = case c of    Covered _ bomb flag -> Covered n bomb flag    Uncovered _ -> Uncovered n    Selected -> SelectedupdateGrid::Grid -> Mat -> GridupdateGrid g m =    let Grid cm = g in    Grid (zipWith (zipWith updateCell) cm m)applyi::(a -> a) -> Int -> [a] -> [a]applyi f i xs =    let (xs1, xs2) = splitAt i xs in    concat [xs1, ( (f (head xs2)) : tail xs2 )]applyij::(a -> a) -> Int -> Int -> [[a]] -> [[a]]applyij f i j xss = applyi (applyi f j) i xssuncover::(Int, Int) -> Grid -> Griduncover (i, j) g =    let Grid cm = g in    let neighbours = tail [(i', j') | i' <- [0, -1, 1], j' <- [0, -1, 1]] in    let uncoverOneCell = \c -> case c of             Covered 0 _ _ -> Uncovered 0 -- TODO : recursion            Covered n _ _ -> Uncovered n    in    Grid (applyij uncoverOneCell i j cm)-- 5) Main LoopcovIndic::Cell -> IntcovIndic (Covered _ _ _) = 1covIndic Selected = 1covIndic _ = 0won::Grid -> Int -> Boolwon g nbMines =    let Grid cm = g in    let nbTotal = (length cm) * (length (cm!!0)) in    let uncoBinMatrix = map (map covIndic) cm in    let nbUnco = sum (map sum uncoBinMatrix) in    nbUnco == nbTotal - nbMinestoggleFlag::Cell -> CelltoggleFlag (Covered n b flag) = Covered n b (not flag)toggleFlag c = cloop::Int -> Int -> Int -> Grid -> IO ()loop i j n b@(Grid xs)    | won n b = putStrLn " Victory !"    | otherwise = do        putStrLn $ show $ Grid $ applyij ( const Selected ) i j xs        c <- getChar        case c of            'i' -> loop (max (i - 1) 0) j n b -- move caret up            'k' -> loop (min (i + 1) ((length xs) - 1)) j n b -- move caret down            'j' -> loop i (max (j - 1) 0) n b -- move caret left            'l' -> loop i (min (j + 1) ((length (xs!!0)) - 1)) n b -- move caret right            'f' -> Grid $ applyij toggleFlag i j b -- toggle flag            'u' -> Grid $ applyij uncover i j b -- uncover tile            otherwise -> loop i j n b -- do nothing-- Testing datadtTinyGrid = Grid [                    [Covered 1 True False, Uncovered 2, Covered 0 True False],                    [Uncovered 0, Uncovered 0, Covered 1 True True]                ]dtRS = randSet 3 SG SG 4 5dtGridCover = grid 4 5 dtRSdtMines = mines dtGridCover
 |