HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Sokoban text clone

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
textsokobanclone

Problem

I rewrote this simple, list-based Sokoban implementation a few times, trying to make it better. Right now, I'm stuck without ideas, but I still feel there is room for improvement, specially in runLoop and data types.

Is there anything, such as monad transformers, FRP, lenses, or anything else that I should study to be able to improve it?

``
module Main where

import Control.Monad.Loops
import Data.Char
import Data.List
import Data.Maybe
import Linear.V2
import System.IO

type Tile = Char
type Level = [[Tile]]
type Position = V2 Int
type Direction = V2 Int

up = V2 0 (-1)
down = V2 0 1
left = V2 (-1) 0
right = V2 1 0

sampleLevel = "############ \n\
\#.. # ###\n\
\#.. # $ $ #\n\
\#.. #$#### #\n\
\#.. @ ## #\n\
\#.. # # $ ##\n\
\###### ##$ $ #\n\
\ # $ $ $ $ #\n\
\ # # #\n\
\ ############\n"

main = do
initialize
runLoop $ readLevel sampleLevel
return ()

initialize :: IO ()
initialize = do
hSetEcho stdin False
hSetBuffering stdin NoBuffering

readLevel :: String -> Level
readLevel = lines

showLevel :: Level -> IO ()
showLevel = putStrLn . unlines

runLoop :: Level -> IO Level
runLoop level = do
showLevel level
if isFinished level then do
putStrLn "Congratulations!"
return level
else do
command getChar
case command of
'W' -> runLoop $ tryMove level $ up
'A' -> runLoop $ tryMove level $ left
'S' -> runLoop $ tryMove level $ down
'D' -> runLoop $ tryMove level $ right
'X' -> return level

isFinished :: Level -> Bool
isFinished = isNothing . findIndex (
elem` ".+") . concat

tryMove :: Level -> Direction -> Level
tryMove level direction = foldl setTile level $ zip positions updatedTiles
where
updatedTiles = case getTile level positions of

Solution

Lens: ix y . ix x can replace your last four definitions.

Why does runLoop return IO Level as opposed to IO () when you never use the Level?

I would inline readLevel, or do you plan to make it more complicated in later versions?

I would change tryMove's type signature into Direction -> Level -> Level.

Context

StackExchange Code Review Q#109065, answer score: 2

Revisions (0)

No revisions yet.