Last active
August 29, 2015 14:00
-
-
Save rblaze/11062822 to your computer and use it in GitHub Desktop.
Minesweeper cheater
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Field = array<bool> | |
let rec printField xsize (field : Field) = | |
let printLine i = Array.sub field (i * xsize) xsize |> Array.map (fun v -> if v then 'X' else '.') | |
[for n in 0 .. field.Length / xsize - 1 -> System.String(printLine n)] | |
let genField size (g : System.Random) = Array.init size (fun _ -> g.Next(100) < 20) | |
let hasMine xsize (field : Field) (x, y) = field.[y * xsize + x] | |
let countMines xsize (field : Field) x y = | |
let ysize = field.Length / xsize | |
let pts = List.filter (fun (px, py) -> px >= 0 && px < xsize && py >= 0 && py <= ysize) [(x-1, y-1); (x, y-1); (x+1, y-1); (x-1, y); (x+1, y); (x-1, y+1); (x, y+1); (x+1, y+1)] | |
List.length <| List.filter (hasMine xsize field) pts | |
let checkField xsize (field : Field) (counts : list<int * int * int>) (mines : list<int * int>) = | |
List.forall (hasMine xsize field) mines && List.forall (fun (x,y,n) -> countMines xsize field x y = n) counts | |
[<EntryPoint>] | |
let main _ = | |
let counts = [(5,6,3); (9,9,2); (6,10,1); (6,11,3)] | |
let mines = [(5,9)] | |
let xsize = 20 | |
let ysize = 20 | |
let rnd = System.Random() | |
let rec findField n = | |
let field = genField (xsize * ysize) rnd | |
if checkField xsize field counts mines then (n, field) else findField (n + 1) | |
let (n, field) = findField 0 | |
let strs = printField xsize field | |
for s in strs do | |
printfn "%s" s | |
printfn "%d" n | |
0 // return an integer exit code |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE BangPatterns #-} | |
module Main where | |
-- assume field 20x20, where user opened few cells | |
-- .................... 0 | |
-- .................... 1 | |
-- .................... 2 | |
-- .................... 3 | |
-- .................... 4 | |
-- .................... 5 | |
-- .....3.............. 6 | |
-- .................... 7 | |
-- .................... 8 | |
-- .....X...2.......... 9 | |
-- ......1............. 10 | |
-- ......3............. 11 | |
-- .................... 12 | |
-- .................... 13 | |
-- .................... 14 | |
-- .................... 15 | |
-- .................... 16 | |
-- .................... 17 | |
-- .................... 18 | |
-- .................... 19 | |
-- 01234567890123456789 | |
-- | |
-- (5,6) = 3 | |
-- (9,9) = 2 | |
-- (6,10) = 1 | |
-- (6,11) = 3 | |
-- (5,9) has mine | |
import System.Random | |
import Data.Vector.Generic ((!)) | |
import qualified Data.Vector.Unboxed as V | |
type Field = V.Vector Bool | |
printField :: Int -> Field -> [String] | |
printField _ field | V.null field = [] | |
printField xsize field = | |
let (r, rs) = V.splitAt xsize field | |
str = map (\v -> if v then 'X' else '.') (V.toList r) | |
in str : printField xsize rs | |
hasMine :: Int -> Field -> Int -> Int -> Bool | |
hasMine xsize field x y = field ! (y * xsize + x) | |
countMines :: Int -> Field -> Int -> Int -> Int | |
countMines xsize field x y = | |
let ysize = V.length field `div` xsize | |
pts = filter (\(px, py) -> px >= 0 && px < xsize && py >=0 && py < ysize) [(x-1, y-1), (x-1, y), (x-1, y+1), (x, y-1), (x, y+1), (x+1, y-1), (x+1,y), (x+1,y+1)] | |
in length $ filter (uncurry $ hasMine xsize field) pts | |
checkField :: Int -> Field -> [(Int, Int, Int)] -> [(Int, Int)] -> Bool | |
checkField xsize field cnts mines = | |
all (uncurry $ hasMine xsize field) mines && | |
all (\(x, y, c) -> countMines xsize field x y == c) cnts | |
genField :: RandomGen r => Int -> r -> Field | |
genField size g = V.fromList $ take size $ map step $ randomRs (0, 100) g | |
where | |
step :: Int -> Bool | |
step n = n < 20 | |
main :: IO () | |
main = do | |
let cnts = [(5,6,3),(9,9,2),(6,10,1),(6,11,3)] | |
let mines = [(5,9)] | |
gen <- getStdGen | |
let loop !n g = do | |
let (g1, g2) = split g | |
let field = genField 400 g1 | |
-- let f = printField 20 field | |
-- mapM_ putStrLn f | |
-- putStrLn ("--- " ++ show n) | |
if checkField 20 field cnts mines | |
then return (n, field) | |
else loop (n + 1 :: Int) g2 | |
(n, field) <- loop 0 gen | |
let f = printField 20 field | |
mapM_ putStrLn f | |
putStrLn ("iteration " ++ show n) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment