-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSudoku.hs
68 lines (54 loc) · 2.44 KB
/
Sudoku.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
module Sudoku
( makeGameEnv
, makeNewGame
, makeGame
) where
import Generator.GeneratorUtil (GeneratorEnv(..), GeneratorStep, CellIndex, generatorSteps, removeCells)
import Generator.FieldGenerator (runFieldGenerator, baseField)
import Generator.GameGenerator (generateGameField)
import qualified Common as Com
import Control.Monad.State (State, evalState, get, put)
import Control.Lens.Getter ((^.))
import System.Random (randoms, randomRs, newStdGen)
import qualified Data.Map.Strict as Map
dropRandomValue :: [a] -> [a]
dropRandomValue = drop 65
takeRandomValues :: [a] -> [a]
takeRandomValues = take 65
makeNewGame :: Com.Difficulties -> IO Com.GameEnv
makeNewGame diff = do
gen <- newStdGen
let randomSteps = randoms gen
cellsToRemove = randomRs (1, 81) gen
genEnv = GeneratorEnv randomSteps cellsToRemove
return $ makeGame genEnv diff
makeGame :: GeneratorEnv -> Com.Difficulties -> Com.GameEnv
makeGame genEnv diff =
let (restSteps, field) = generateField (genEnv ^. generatorSteps)
(restCells, gameField) = generateGame (genEnv ^. removeCells) field diff
in makeGameEnv field gameField diff $ GeneratorEnv restSteps restCells
generateField :: [GeneratorStep] -> ([GeneratorStep], Com.Field)
generateField steps =
let currSteps = takeRandomValues steps
genField = runFieldGenerator currSteps baseField
in (dropRandomValue steps, genField)
generateGame :: [CellIndex] -> Com.Field -> Com.Difficulties -> ([CellIndex], Com.GameField)
generateGame cellsToRemove genField difficult =
let genGame = generateGameField genField cellsToRemove difficult
in (dropRandomValue cellsToRemove, genGame)
makeGameEnv :: Com.Field -> Com.GameField -> Com.Difficulties -> GeneratorEnv -> Com.GameEnv
makeGameEnv field gameField diff genEnv =
let cells = concat $ evalState (mapM collectCellCoord gameField) 0
cellsMap = Map.fromList cells
in Com.GameEnv field gameField cellsMap diff genEnv
where
collectCellCoord :: [Com.Cell] -> State Int [(Com.CellCoord, Com.CellValue)]
collectCellCoord row = do
rowNumber <- get
let zippedCells = filter (\(_, cell) -> isOpenedCell cell) (zip [0..8] row)
mappedRow = map (\(column, (Com.Opened value)) -> ((column, rowNumber), value)) zippedCells
put (rowNumber + 1)
return mappedRow
isOpenedCell :: Com.Cell -> Bool
isOpenedCell Com.Closed = False
isOpenedCell (Com.Opened _) = True