Last active
October 1, 2018 09:20
-
-
Save pphetra/637b5ec37a01fc42b7f62b53723f9d02 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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