wha*_*ley 4 functional-programming scala game-loop
我刚刚开始使用Scala,我正在尝试一个小玩具程序 - 在这种情况下是一个基于文本的TicTacToe.我根据我对scala的了解编写了一个工作版本,但注意到它主要是必要的,我的课程是可变的.
我正在尝试实现一些功能习惯用法,并且设法至少使表示游戏状态的类不可变.但是,我留下了一个负责执行游戏循环的类,依赖于可变状态和命令循环,如下所示:
var board: TicTacToeBoard = new TicTacToeBoard
def start() {
var gameState: GameState = new XMovesNext
outputState(gameState)
while (!gameState.isGameFinished) {
val position: Int = getSelectionFromUser
board = board.updated(position, gameState.nextTurn)
gameState = getGameState(board)
outputState(gameState)
}
}
Run Code Online (Sandbox Code Playgroud)
在这个循环中编写我正在做什么的更具惯用性的方法是什么?
完整的源代码在这里https://github.com/whaley/TicTacToe-in-Scala/tree/master/src/main/scala/com/jasonwhaley/tictactoe
对于Scala来说,命令性循环很好.你总是可以写一个递归函数来表现得像一个循环.我也投入了一些模式匹配.
def start() {
def loop(board: TicTacToeBoard) = board.state match {
case Finished => Unit
case Unfinished(gameState) => {
gameState.output()
val position: Int = getSelectionFromUser()
loop(board.updated(position))
}
}
loop(new TicTacToeBoard)
}
Run Code Online (Sandbox Code Playgroud)
假设我们有一个函数whileSome : (a -> Option[a]) a -> (),它运行输入函数,直到结果为None.那会剥掉一些样板.
def start() {
def step(board: TicTacToeBoard) = {
board.gameState.output()
val position: Int = getSelectionFromUser()
board.updated(position) // returns either Some(nextBoard) or None
}
whileSome(step, new TicTacToeBoard)
}
Run Code Online (Sandbox Code Playgroud)
whileSome写作应该是微不足道的; 它只是前一种模式的抽象.我不确定它是否在任何常见的Scala库中,但在Haskell中你可以whileJust_从monad-loops中获取.
您可以将其实现为递归方法.这是一个不相关的例子:
object Guesser extends App {
val MIN = 1
val MAX = 100
readLine("Think of a number between 1 and 100. Press enter when ready")
def guess(max: Int, min: Int) {
val cur = (max + min) / 2
readLine("Is the number "+cur+"? (y/n) ") match {
case "y" => println("I thought so")
case "n" => {
def smallerGreater() {
readLine("Is it smaller or greater? (s/g) ") match {
case "s" => guess(cur - 1, min)
case "g" => guess(max, cur + 1)
case _ => smallerGreater()
}
}
smallerGreater()
}
case _ => {
println("Huh?")
guess(max, min)
}
}
}
guess(MAX, MIN)
}
Run Code Online (Sandbox Code Playgroud)