DEV Community

Discussion on: Daily Challenge #207 - Snakes and Ladders

Collapse
 
avalander profile image
Avalander • Edited

Scala

Instead of saving the state internally, the play function receives a state object and returns a new state object to keep it pure.

object LaddersAndSnakes {
  private val links = Map(
    2 -> 38,
    7 -> 14,
    8 -> 31,
    15 -> 26,
    16 -> 6,
    21 -> 42,
    28 -> 84,
    36 -> 44,
    46 -> 25,
    49 -> 11,
    51 -> 67,
    62 -> 19,
    64 -> 60,
    71 -> 91,
    74 -> 53,
    78 -> 98,
    87 -> 94,
    92 -> 88,
    95 -> 75,
    99 -> 80,
  )

  sealed trait Player
  case object Player1 extends Player
  case object Player2 extends Player

  sealed trait State
  case class Playing(p1: Int, p2: Int, next: Player) extends State {
    val nextPos = next match {
      case Player1 => p1
      case Player2 => p2
    }
  }
  case class Win(p: Player) extends State
  case object GameOver extends State

  object State {
    def start (): State = Playing(1, 1, Player1)
  }

  type Roll = (Int, Int)


  def play (s: State, r: Roll): State = s match {
    case GameOver           => GameOver
    case Win(_)             => GameOver
    case Playing(p1, p2, n) => nextTurn(Playing(p1, p2, n), r)
  }

  private def nextTurn (s: Playing, roll: Roll): State = {
    val Playing(p1, p2, next) = s
    val player = s.nextPos
    val nextPos = updatePosition(player, roll)

    if (nextPos == 100) Win(next)
    else if (isDouble(roll)) next match {
      case Player1 => Playing(nextPos, p2, Player1)
      case Player2 => Playing(p1, nextPos, Player2)
    }
    else next match {
      case Player1 => Playing(nextPos, p2, Player2)
      case Player2 => Playing(p1, nextPos, Player1)
    }
  }

  private def updatePosition (pos: Int, roll: Roll): Int = {
    val (d1, d2) = roll
    val nextPos = clamp(pos + d1 + d2, 100)

    links get nextPos match {
      case None    => nextPos
      case Some(v) => v
    }
  }

  private def clamp (v: Int, limit: Int): Int = {
    if (v <= limit) v
    else limit - (v - limit)
  }

  private def isDouble (r: Roll): Boolean = {
    r._1 == r._2
  }
}
Collapse
 
dynamicboy24 profile image
DynamicBoy24

which language is this