Flipping bits game: Difference between revisions

Content added Content deleted
m (→‎{{header|Perl 6}}: numeric sorting of rows)
(→‎{{header|Haskell}}: Specified imports, applied hlint, hindent)
Line 1,264:
=={{header|Haskell}}==
Maximum game size is 9x9 because the array indices are the characters 1 until 9.
<lang Haskell>import Data.Array (Array, (!), (//), array, bounds)
 
import Data.Array
import Data.List (intersperse)
 
import Control.Monad
import Control.Monad (zipWithM_, replicateM, foldM, when)
import System.Random
 
import System.Random (randomRIO)
 
type Board = Array (Char, Char) Int
Line 1,276 ⟶ 1,278:
flp 1 = 0
 
numRows, numCols :: Board -> [Char]String
numRows t =
numRows t = let ((a, _), (b, _)) = bounds t in [a .. b]
in [a .. b]
 
numCols t =
numCols t = let ((_, a), (_, b)9) = bounds t in [a .. b]
in [a .. b]
 
numCols t = let ((_, a), (_, b)) = bounds t in [a .. b]
flipRow, flipCol :: Board -> Char -> Board
flipRow t r = let e = [ (ix, flp (t ! ix)) | ix <-
let e =
zip (repeat r) (numCols t) ]
[ (ix, flp in (t //! eix))
| ix <- zip (repeat r) (numCols t) ]
in t // e
 
flipCol t c = let e = [ (ix, flp (t ! ix)) | ix <-
let e =
zip (numRows t) (repeat c) ]
[ (ix, flp in (t //! eix))
| ix <- zip (numRows t) (repeat c) ]
in t // e
 
printBoard :: Board -> IO ()
printBoard t = do
let rows = numRows t
cols = numCols t
f 0 = '0'
f 1 = '1'
p r xs = putStrLn $ [r, ' '] ++ intersperse ' ' (map f xs)
putStrLn $ " " ++ intersperse ' ' cols
zipWithM_
zipWithM_ p rows [ [ t ! (y, x) | x <- cols ] | y <- rows ]
p
whererows
[ [ t ! (y, x)
start | x <- docols ]
| y <- rows ]
 
-- create a random goal board, and flip rows and columns randomly
-- to get a starting board
setupGame :: Char -> Char -> IO (Board, Board)
setupGame sizey sizex = do
-- random cell value at (row, col)
= do
let mk rc = fmap (\v -> (rc, v)) $ randomRIO (0, 1)
let mk rc = (\v -> rows(rc, =v)) <$> ['a'randomRIO ..(0, sizey]1)
colsrows = ['1a' .. sizexsizey]
goal <- fmapcols (array (('a',= ['1'), (sizey,.. sizex))) $]
goal <-
mapM mk [ (r, c) | r <- rows, c <- cols ]
array (('a', '1'), (sizey, sizex)) <$>
start <- do
mapM
let change :: Board -> Int -> IO Board
mk
-- flip random row
[ (r, c)
change t 0 = fmap (flipRow t) $ randomRIO ('a', sizey)
| r <-- flip randomrows col
, c <- cols ]
change t 1 = fmap (flipCol t) $ randomRIO ('1', sizex)
start <-
numMoves <- randomRIO (3, 15) -- how many flips (3 - 15)
do let change :: Board -> Int -> IO Board
-- determine if rows or cols are flipped
moves <- replicateM numMoves $ randomRIO-- (0,flip 1)random row
change t 0 = fmap (flipRow t) <$> randomRIO ('a', sizey)
-- make changes and get a starting board
foldM change goal moves-- flip random col
change t 1 = fmap (flipCol t) <$> randomRIO ('1', sizex)
if goal /= start -- check if boards are different
numMoves then<- returnrandomRIO (goal3, start15) -- allhow ok,many returnflips both(3 boards- 15)
-- elsedetermine setupGameif sizeyrows sizexor --cols tryare againflipped
let mk rc = fmap (\vmoves <-> (rc,replicateM v))numMoves $ randomRIO (0, 1)
-- make changes and get a starting board
foldM turnschange goal current moves = do
if goal /= start -- check if boards are different
then return (goal, start) -- all ok, return both boards
else setupGame sizey sizex -- try again
 
main :: IO ()
main = do
putStrLn "Select a board size (1 - 9).\nPress any other key to exit."
sizec <- getChar
when (sizec `elem` ['1' .. '9']) $ do
do let size = read [sizec] - 1
(g, s) <- setupGame (['a' ..] !! size) (['1' ..] !! size)
turns g s 0
where
turns goal current moves = do
where
putStrLn "\nGoal:"
turns goal current moves = do
printBoard goal
putStrLn "\nGoal:"
putStrLn "\nBoard:"
printBoard goal
printBoard current
putStrLn "\nBoard:"
when (moves > 0) printBoard current$
putStrLn $ "\nYou've made when" ++ show (moves >++ 0)" $moves so far."
putStrLn $ "\nYou've made " ++ show moves ++ " moves so far."
putStrLn $ "\nFlip a row (" ++ numRows current ++
numRows current ++ ") or a column (" ++ numCols current ++ ")"
v <- getChar
if v `elem` numRows current
then check $ flipRow current v
else if v `elem` numCols current
then check $ flipCol current v
else tryAgain
where
where check t = if t == goal
if t == goal
then putStrLn $ "\nYou've won in " ++
then putStrLn $ "\nYou've won in " ++ show (moves + 1) ++ " moves!"
else turns goal t (moves + 1)
tryAgain = do
putStrLn ": Invalid row or tryAgain = docolumn."
turns goal current moves</lang>
putStrLn ": Invalid row or column."
{{Out}}
turns goal current moves
<pre>Select a board size (1 - 9).
</lang>
<b>Output:</b>
<pre>
Select a board size (1 - 9).
Press any other key to exit.
3
Line 1,395 ⟶ 1,413:
Flip a row (abc) or a column (123)
c
You've won in 2 moves!</pre>
</pre>
 
=={{header|J}}==