review feedback

This commit is contained in:
kageru 2020-10-29 16:41:24 +01:00
parent 5237cad9a4
commit 10d70c6f84
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
2 changed files with 15 additions and 17 deletions

View File

@ -1,18 +1,15 @@
package rps package rps
import kotlin.random.Random
const val TURNS = 100 const val TURNS = 100
val PLAYER_TWO_CHOICE = Move.ROCK
fun main() { fun main() {
println("Outcome from Player 1’s perspective: ${playGame(TURNS)}") println("Outcome from Player 1’s perspective: ${playGame(TURNS)}")
} }
/** Determine the [Outcome] of [first] vs [second] from the perspective of [first]. */ /** Determine the [Outcome] of [first] vs [second] from the perspective of [first]. */
fun determineOutcome(first: Move, second: Move): Outcome = when { fun determineOutcome(first: Move, second: Move): Outcome = when(second) {
first.strongAgainst() == second -> Outcome.WIN in first.strongAgainst() -> Outcome.WIN
first == second -> Outcome.DRAW first -> Outcome.DRAW
else -> Outcome.LOSS else -> Outcome.LOSS
} }
@ -24,15 +21,13 @@ fun List<Outcome>.calculateGameSummary() = GameSummary(
losses = count { it == Outcome.LOSS }, losses = count { it == Outcome.LOSS },
) )
fun playGame(turns: Int): GameSummary = generateSequence { randomMove() } fun playGame(turns: Int): GameSummary = generateSequence { randomMove() to randomMove() }
.take(turns) .take(turns)
.map { determineOutcome(it, PLAYER_TWO_CHOICE) } .map { (p1, p2) -> determineOutcome(p1, p2) }
.toList() .toList()
.calculateGameSummary() .calculateGameSummary()
fun randomMove(): Move = Move.values().let { allMoves -> fun randomMove(): Move = Move.values().random()
allMoves[Random.nextInt(allMoves.size)]
}
/* /*
* Classes and named tuples below this point. * Classes and named tuples below this point.
@ -43,13 +38,13 @@ fun randomMove(): Move = Move.values().let { allMoves ->
* A possible move in a game of rock-paper-scissors. * A possible move in a game of rock-paper-scissors.
* *
* [strongAgainst] is a function for lazy evaluation because otherwise we cant access SCISSORS before its been defined. * [strongAgainst] is a function for lazy evaluation because otherwise we cant access SCISSORS before its been defined.
* If the game needs to be expanded (e.g. the somewhat common rock, paper, scissors, salamander, spock),
* this argument could be a List<Move> instead.
*/ */
enum class Move(val strongAgainst: () -> Move) { enum class Move(val strongAgainst: () -> Set<Move>) {
ROCK({ SCISSORS }), ROCK({ setOf(SCISSORS, LIZARD) }),
PAPER({ ROCK }), PAPER({ setOf(ROCK, SPOCK) }),
SCISSORS({ PAPER }) SCISSORS({ setOf(PAPER, LIZARD) }),
LIZARD({ setOf(SPOCK, PAPER) }),
SPOCK({ setOf(SCISSORS, ROCK) }),
} }
// purposely not calling this Result to avoid confusion with kotlin.Result and similar // purposely not calling this Result to avoid confusion with kotlin.Result and similar

View File

@ -13,6 +13,9 @@ class GameTest {
Triple(ROCK, PAPER, LOSS), Triple(ROCK, PAPER, LOSS),
Triple(PAPER, SCISSORS, LOSS), Triple(PAPER, SCISSORS, LOSS),
Triple(ROCK, ROCK, DRAW), Triple(ROCK, ROCK, DRAW),
Triple(ROCK, LIZARD, WIN),
Triple(LIZARD, SPOCK, WIN),
Triple(SPOCK, PAPER, LOSS),
) )
for ((first, second, expected) in games) { for ((first, second, expected) in games) {
assertEquals(determineOutcome(first, second), expected) assertEquals(determineOutcome(first, second), expected)