diff --git a/src/Game/Board.hs b/src/Game/Board.hs index 0584dd1..2c4e3fa 100644 --- a/src/Game/Board.hs +++ b/src/Game/Board.hs @@ -2,7 +2,7 @@ module Game.Board ( generateBoard, - revealCell, + reveal, revealAllNonFlaggedCells, flagCell, checkLost, @@ -22,23 +22,23 @@ module Game.Board ) where -import Control.Lens -import Data.List -import Data.Matrix -import Data.Matrix.Lens (elemAt, flattened, size) -import System.Random -import System.Random.Shuffle +import Control.Lens +import Data.List +import Data.Matrix +import Data.Matrix.Lens (elemAt, flattened, size) +import System.Random +import System.Random.Shuffle type Dimension = (Int, Int) type Coordinate = (Int, Int) data Cell = Cell - { _isFlagged :: Bool, - _isRevealed :: Bool, - _hasBomb :: Bool, + { _isFlagged :: Bool, + _isRevealed :: Bool, + _hasBomb :: Bool, _neighboringBombs :: Int, - _coordinate :: Coordinate + _coordinate :: Coordinate } deriving (Show, Eq) @@ -79,6 +79,10 @@ generateBoard (h, w) bombCount seed = setCellToRevealed :: Board -> Coordinate -> Board setCellToRevealed board c = board & elemAt c . isRevealed .~ True +-- wrapper for the reveal actions, if a cell is not revealed yet, reveal it, otherwise try a quick reveal +reveal :: Board -> Coordinate -> Board +reveal board c = if board ^. (elemAt c . isRevealed) then quickReveal board c else revealCell board c + -- Reveals a cell at a given coordinate for a given Board -- Rule explanation: will also reveal any direct neighbouring Cells which have no bomb and their neighbour cells if the have 0 neighboring bombs revealCell :: Board -> Coordinate -> Board @@ -102,6 +106,23 @@ revealCell board c = resultBoard -- In any other case just reveal the cell at (i,j) _ -> setCellToRevealed board c +-- Quick reveal +-- If a cell is revealed, has more than one neighboring bomb and the bomb count matches the amount of flagged neighbors all non flagged neighbours can bo quick revealed +quickReveal :: Board -> Coordinate -> Board +quickReveal board c = resultBoard + where + dim = getDimensionsForBoard board + cellIsRevealed = board ^. (elemAt c . isRevealed) + neighbourCoordinates = neighbourCells c dim + neighbours = filter (\cell -> cell ^. coordinate `elem` neighbourCoordinates) (toList board) + bombNeighbourCount = board ^. (elemAt c . neighboringBombs) + nonFlaggedNeighboursCoordinates = map _coordinate $ filter (\x -> not (x ^. isFlagged)) neighbours + flaggedNeighboursCount = length $ filter (^. isFlagged) neighbours + -- move is only valid if c is revealed, has neighboring bombs and if the neighboringBombs match the number of flagged neighbours + isValidMove = cellIsRevealed && bombNeighbourCount > 0 && bombNeighbourCount == flaggedNeighboursCount + --if the move is valid reveal all neighbour cells otherwise return the initial board + resultBoard = if isValidMove then foldl setCellToRevealed board nonFlaggedNeighboursCoordinates else board + -- Reveals all cells which have not been flagged revealAllNonFlaggedCells :: Board -> Board revealAllNonFlaggedCells board = board & flattened . filtered (not . _isFlagged) . isRevealed .~ True diff --git a/src/Game/Game.hs b/src/Game/Game.hs index fa934c9..c5ee36b 100644 --- a/src/Game/Game.hs +++ b/src/Game/Game.hs @@ -83,7 +83,7 @@ makeMove state m = where (boardAfterMove, time) = case m of (Flag c t) -> (flagCell (state ^. board) c, t) - (Reveal c t) -> (revealCell (state ^. board) c, t) + (Reveal c t) -> (reveal (state ^. board) c, t) (RevealAllNonFlagged t) -> (revealAllNonFlaggedCells (state ^. board), t) finishGame = calculateTimeElapsed (state ^. lastStartedAt) (state ^. timeElapsed) time st = checkStatus boardAfterMove diff --git a/templates/game.hamlet b/templates/game.hamlet index 69336d3..9930af4 100644 --- a/templates/game.hamlet +++ b/templates/game.hamlet @@ -33,7 +33,7 @@ Left Click to reveal a cell. - Alt + Click + Right Click to flag a cell.
  • Click the face to restart. A new seed will be chosen. @@ -62,7 +62,7 @@ $forall cellEntity <- row ^. rowCells $if (gameStateEntity ^. gameStateEntityStatus) == "Ongoing" -
    +
    $else
    diff --git a/templates/game.julius b/templates/game.julius index abe6fb4..1d811ed 100644 --- a/templates/game.julius +++ b/templates/game.julius @@ -18,14 +18,28 @@ var src; const makeMove = (x, y, gameId, event) => { event.preventDefault(); - console.log("MAKE MOVE", { x, y, gameId, event }); + console.log("MAKE MOVE", { x, y, gameId }, "EVENT", { + button: event.button, + event, + }); + + var action = null; + if (event.button === 0) { + action = "Reveal"; + } else if (event.button === 2) { + action = "Flag"; + } + + if (action === null) { + return; + } $.ajax({ url: "/game/" + gameId, type: "PUT", contentType: "application/json", data: JSON.stringify({ - action: event.altKey ? "Flag" : "Reveal", + action: action, coordX: x, coordY: y, }),