Skip to content

Instantly share code, notes, and snippets.

@pphetra
Last active October 1, 2018 09:20
Show Gist options
  • Save pphetra/637b5ec37a01fc42b7f62b53723f9d02 to your computer and use it in GitHub Desktop.
Save pphetra/637b5ec37a01fc42b7f62b53723f9d02 to your computer and use it in GitHub Desktop.
package com.example
import akka.actor.ActorSystem
import akka.stream._
import akka.stream.scaladsl.Source
import akka.{Done, NotUsed}
import scala.collection.immutable.ListSet
import scala.concurrent.{ExecutionContextExecutor, Future}
object Hangman {
sealed trait Status
case object IN_PROGRESS extends Status
case object WIN extends Status
case object LOSS extends Status
sealed case class GameState(status: Status, selectedLetters: ListSet[Char], lifeLeft: Int, secretWordLength: Int,
knownSecretWord: String) {
override def toString: String = {
s"status: $status, selectedLetters: $selectedLetters, lifeLeft: $lifeLeft, knownSecretWord: $knownSecretWord"
}
}
class Game(secretWord: String) {
def initState: GameState = {
GameState(IN_PROGRESS, ListSet(), 7, secretWord.length, secretWord.map(_ => '_'))
}
def reducer(state: GameState, letter: Char): GameState = {
if (state.selectedLetters.contains(letter) || state.status == LOSS) { // already guess or loss
return state
}
val selectedLetters = state.selectedLetters + letter
var found = false
if (secretWord.contains(letter)) {
found = true
}
val lifeLeft = state.lifeLeft - (if (found) 0 else 1)
val knownSecretWord = secretWord.map(ch => {
if (selectedLetters.contains(ch)) ch else '_'
})
val status = if (lifeLeft <= 0) LOSS else
if (knownSecretWord.contains('_')) IN_PROGRESS else WIN
state.copy(
selectedLetters = selectedLetters,
lifeLeft = lifeLeft,
knownSecretWord = knownSecretWord,
status = status
)
}
}
def streamHangman(secretWord: String, source: Source[Char, NotUsed]): Source[GameState, NotUsed] = {
val game = new Hangman.Game(secretWord)
source.scan(game.initState)(game.reducer)
}
}
//#main-class
object HangmanApp extends App {
implicit val system: ActorSystem = ActorSystem("hangman")
implicit val materializer: ActorMaterializer = ActorMaterializer()
val source: Source[Char, NotUsed] = Source(List('a', 'b', 'e', 'l', 'o', 'h'))
val done: Future[Done] = Hangman.streamHangman("hello", source).runForeach(state ⇒ println(state))(materializer)
implicit val ec: ExecutionContextExecutor = system.dispatcher
done.onComplete(_ ⇒ system.terminate())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment