Skip to content

Commit c303e23

Browse files
author
Daniel Barclay
committed
ManualTicTacToe: Added "private" to GameUI method; edited lots of comments.
1 parent 5df93ba commit c303e23

File tree

2 files changed

+37
-32
lines changed

2 files changed

+37
-32
lines changed

src/main/scala/com/us/dsb/explore/algs/ttt/manual/GameUI.scala

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,26 @@ package com.us.dsb.explore.algs.ttt.manual
22

33
import cats.syntax.option._
44
import cats.syntax.either._
5-
import enumeratum.EnumEntry
5+
import enumeratum.{Enum, EnumEntry}
66

77
import scala.annotation.tailrec
88

9+
// ?? any substantial benefit to moving internal methods to class? we could
10+
// avoid some state passing, but only by mutating top-level state member
911

10-
//???? object -> class?
1112
/** TTT UI controller. */
1213
object GameUI {
1314

1415
// ??? enhance; maybe just put clean strings in; maybe build on GameResult (plus quit case)
1516
case class GameUIResult(text: String)
1617

18+
// ("extends EnumEntry" gets .entryName, enables Enum; "extends Enum[...]"
19+
// enables (and requires) .values.
1720

18-
sealed trait UICommand extends EnumEntry
19-
object UICommand {
20-
// ?? why doesn't UICommand's "sealed" obviate the following one (for exhaustive-match checks?)
21+
private sealed trait UICommand
22+
private object UICommand {
23+
// (Q: Why doesn't UICommand's "sealed" obviate the following one (for
24+
// exhaustive-match checks)?
2125
sealed trait UIMoveCommand extends UICommand
2226
case object Up extends UIMoveCommand
2327
case object Down extends UIMoveCommand
@@ -26,8 +30,15 @@ object GameUI {
2630
case object Mark extends UICommand
2731
case object Quit extends UICommand
2832
}
33+
// ?? Decide "UICommand._" re little scala.Right ~clashes.
2934

30-
def parseCommand(rawCmd: String): Either[String, UICommand] = {
35+
// (Could put strings in enumerators and use Enum.withName to factor down
36+
// parse function, but then layers wouldn't be separated.)
37+
38+
// ?? revisit String (but may be fine since dealing with input _strings_
39+
// from _user_
40+
// ?? revisit Either--use something fancier (MonadError)?
41+
private def parseCommand(rawCmd: String): Either[String, UICommand] = {
3142
import UICommand._
3243
rawCmd match {
3344
case "u" => Up.asRight
@@ -42,11 +53,13 @@ object GameUI {
4253
}
4354

4455
@tailrec
45-
def getCommand(player: Player): UICommand = {
46-
// ?? clean embedded reference to stdin/console and stdout
56+
private def getCommand(player: Player): UICommand = {
57+
58+
// ?? clean embedded references to stdin/console and stdout
4759
print(s"Player $player command?: ")
4860
val rawCmd = scala.io.StdIn.readLine()
4961

62+
import scala.Left
5063
parseCommand(rawCmd) match {
5164
case Right(cmd) => cmd
5265
case Left(msg) =>
@@ -55,9 +68,9 @@ object GameUI {
5568
}
5669
}
5770

58-
//import UICommand.UIMoveCommand
59-
def moveSelection(uiState: GameUIState,
60-
moveCommand: UICommand.UIMoveCommand): GameUIState = {
71+
private def moveSelection(uiState: GameUIState,
72+
moveCommand: UICommand.UIMoveCommand
73+
): GameUIState = {
6174
import UICommand._
6275
moveCommand match {
6376
case Up => uiState.withRowAdustedBy(-1)
@@ -68,34 +81,30 @@ object GameUI {
6881
}
6982

7083
// ?? "place mark"?
71-
def markAtSelection(uiState: GameUIState): GameUIState = {
84+
private def markAtSelection(uiState: GameUIState): GameUIState = {
7285
val moveResult = uiState.gameState.tryMoveAt(uiState.selectedRow,
7386
uiState.selectedColumn)
7487
moveResult match {
7588
case Right(newGameState) =>
7689
uiState.copy(gameState = newGameState)
7790
case Left(errorMsg) =>
78-
// ?? clean I/O? add to result and hjave cmd loop show? call ~injected error reporter?
91+
// ?? clean I/O? add to result and have cmd loop show? call ~injected error reporter?
7992
println(errorMsg)
8093
uiState // no change
8194
}
8295
}
8396

84-
def doQuit(uiState: GameUIState): GameUIResult = {
97+
private def doQuit(uiState: GameUIState): GameUIResult = {
8598
GameUIResult("Game was quit")
8699
}
87100

88-
89-
90-
91-
92101
// ?? clean looping more (was while mess, now recursive; is there better Scala way?)
93102
/**
94103
* Logically, loops on prompting for and executing user UI ~commands until
95104
* game over or quit.
96105
*/
97106
@tailrec
98-
def getAndDoUiCommands(uiState: GameUIState): GameUIResult = {
107+
private def getAndDoUiCommands(uiState: GameUIState): GameUIResult = {
99108
println()
100109
println(uiState.toDisplayString)
101110

@@ -107,34 +116,30 @@ object GameUI {
107116
case Quit =>
108117
doQuit(uiState)
109118
case move: UIMoveCommand => // any move-selection command
110-
getAndDoUiCommands(moveSelection(uiState, move))
119+
val nextState = moveSelection(uiState, move)
120+
getAndDoUiCommands(nextState)
111121
case Mark =>
112-
val newUiState = markAtSelection(uiState)
113-
newUiState.gameState.gameResult match {
122+
val nextState = markAtSelection(uiState)
123+
nextState.gameState.gameResult match {
114124
case None => // game not done yet
115-
getAndDoUiCommands(newUiState)
125+
getAndDoUiCommands(nextState)
116126
case Some(gameResult) =>
117-
118-
import GameState.GameResult._
127+
import GameState.GameResult._ // ???
119128
val textResult =
120129
gameResult match {
121130
case Draw => "Game ended in draw"
122131
case Win(player) => s"Player $player won"
123132
}
124-
GameUIResult(textResult) // ?? refine from text
133+
GameUIResult(textResult) // ?? refine from text?
125134
}
126135
}
127136
}
128137

129138
def runGame(): GameUIResult = {
130-
// ???? construct GameUIState
131-
// ???? _maybe_ move GamUIeState into GameUI and not pass around methods
132139
val initialState =
133-
// ?? maybe clean getting indices; maybe get from index ranges, not
134-
// constructing here (though here exercises refined type_)
135140
GameUIState(GameState.initial, RowIndex(Index(1)), ColumnIndex(Index(1)))
136141

137-
GameUI.getAndDoUiCommands(initialState)
142+
getAndDoUiCommands(initialState)
138143

139144
}
140145

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.us.dsb.explore.algs.ttt.manual
22

33
object ManualTicTacToe extends App {
4-
val gameResult2 = GameUI.runGame() //???? specify starting user?
4+
val gameResult2 = GameUI.runGame() // ?? specify starting user?
55
println("Result: " + gameResult2.text)
66
}

0 commit comments

Comments
 (0)