Advertisement
Guest User

Untitled

a guest
Jan 12th, 2015
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 2.26 KB | None | 0 0
  1. import scala.annotation.tailrec
  2. import scala.util.Random
  3.  
  4. trait Cell
  5. trait Revealed extends Cell
  6.  
  7. case object Mine extends Revealed
  8. case object Safe extends Revealed
  9.  
  10. case class Unsafe(surrounding: Int) extends Revealed
  11. case class Unknown(covers: Revealed) extends Cell
  12. case class Flag(covers: Revealed) extends Cell
  13.  
  14. case class Point(x: Int, y: Int)
  15. case class Board(width: Int, height: Int, cells: Map[Point, Cell])
  16.  
  17. object Minesweeper {
  18.   def newGame(numberOfMines: Int, width: Int, height: Int): Board = {
  19.     val positions = for {x <- 0 until width
  20.                          y <- 0 until height} yield Point(x, y)
  21.     val rndPos = Random.shuffle(positions)
  22.     val mines = rndPos.take(numberOfMines).map(_ -> Unknown(Mine))
  23.     val safes = rndPos.drop(numberOfMines).map(_ -> Unknown(Safe))
  24.     Board(width, height, mines.toMap ++ safes)
  25.   }
  26.  
  27.   def flag(p: Point, board: Board): Board = board.cells(p) match {
  28.     case Unknown(covers) => Board(board.width, board.height, board.cells + (p -> Flag(covers)))
  29.     case Flag(covers) => Board(board.width, board.height, board.cells + (p -> Unknown(covers)))
  30.     case _ => board
  31.   }
  32.  
  33.   def reveal(p: Point, board: Board): Board = reveal(Set(p), Set.empty, board)
  34.  
  35.   @tailrec
  36.   private def reveal(points: Set[Point], revealed: Set[Point], board: Board): Board = {
  37.     points.diff(revealed).toList match {
  38.       case Nil => board
  39.       case (r: Revealed) :: rest => reveal(rest.toSet, revealed + r, board)
  40.       case c :: rest =>
  41.         val neighs = findNeighbours(c, board)
  42.         val nearbyMines = neighs.count {
  43.           case (p, Mine) => true
  44.           case (p, Unknown(Mine)) => true
  45.           case _ => false
  46.         }
  47.         val afterReveal = if (nearbyMines > 0) Unsafe(nearbyMines) else Safe
  48.         val newBoard = Board(board.width, board.height, board.cells + (c -> afterReveal))
  49.         val remaining = rest ++ neighs.map { case (point, cell) => point}
  50.         reveal(remaining.toSet, revealed + c, newBoard)
  51.     }
  52.   }
  53.  
  54.   private def findNeighbours(p: Point, board: Board) = for {
  55.     dx <- -1 to 1
  56.     dy <- -1 to 1
  57.     nx = p.x + dx
  58.     ny = p.y + dy
  59.     if nx >= 0 && nx < board.width
  60.     if ny >= 0 && ny < board.height
  61.     point = Point(nx, ny)
  62.   } yield (point, board.cells(point))
  63. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement