Hangman 2 with Scala Akka
|
package in.norbor.bigbears.hangman2 |
|
|
|
import akka.actor.{ActorRef, ActorSystem, Props} |
|
import akka.pattern.ask |
|
import akka.util.Timeout |
|
|
|
import scala.concurrent.ExecutionContext.Implicits.global |
|
import scala.concurrent.duration._ |
|
import scala.io.StdIn |
|
import scala.language.postfixOps |
|
import scala.util.{Failure, Success} |
|
|
|
/** |
|
* @author Peerapat A on Oct 1, 2018 |
|
*/ |
|
object Main extends App { |
|
|
|
private implicit val timeout: Timeout = Timeout(13 seconds) |
|
|
|
private val streamer = start("bigbears") |
|
|
|
while (true) |
|
(streamer ? StdIn.readChar()) |
|
.onComplete { |
|
case Success(s: State) => |
|
println(s) |
|
if (s.status != Status.InGame) |
|
System.exit(0) |
|
|
|
case Failure(e) => |
|
e.printStackTrace() |
|
} |
|
|
|
def start(word: String): ActorRef = system.actorOf(Props(classOf[Streamer]), word) |
|
|
|
private lazy val system: ActorSystem = ActorSystem("Norbor") |
|
|
|
} |
|
package in.norbor.bigbears.hangman2 |
|
|
|
import in.norbor.bigbears.hangman2.Status.Status |
|
|
|
/** |
|
* @author Peerapat A on Oct 1, 2018 |
|
*/ |
|
case class State(selected: List[Char] |
|
, status: Status |
|
, lifeLeft: Int) { |
|
|
|
def knownSecret: String = selected.mkString("") |
|
|
|
def correct(update: List[Char]): State = if (update.contains('_')) |
|
this.copy(selected = update) |
|
else |
|
this.copy(status = Status.Win, selected = update) |
|
|
|
} |
|
|
|
object State { |
|
|
|
def apply(word: String): State = State( |
|
status = Status.InGame |
|
, selected = word.map(_ => '_').toList |
|
, lifeLeft = 7) |
|
|
|
} |
|
package in.norbor.bigbears.hangman2 |
|
|
|
/** |
|
* @author Peerapat A on Oct 1, 2018 |
|
*/ |
|
object Status extends Enumeration { |
|
type Status = Value |
|
|
|
val InGame: Value = Value |
|
val Win: Value = Value |
|
val Lose: Value = Value |
|
} |
|
package in.norbor.bigbears.hangman2 |
|
|
|
import akka.actor.Actor |
|
|
|
/** |
|
* @author Peerapat A on Oct 1, 2018 |
|
*/ |
|
class Streamer extends Actor { |
|
|
|
private val word = self.path.name |
|
private var state = State(word) |
|
private val secret = self.path.name.toCharArray |
|
|
|
def receive: PartialFunction[Any, Unit] = { |
|
case c: Char => |
|
state = if (!secret.contains(c)) |
|
if (state.lifeLeft > 0) |
|
state.copy(lifeLeft = state.lifeLeft - 1) |
|
else |
|
state.copy(status = Status.Lose) |
|
else |
|
state.correct(secret.zipWithIndex.filter(_._1 == c).map(_._2).foldLeft(state.selected)((x, y) => x.patch(y, Seq(c), 1))) |
|
|
|
sender() ! state |
|
} |
|
|
|
} |