Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Functional Alternative to Game Loop

I'm just starting out with the Scala and am trying a little toy program - in this case a text based TicTacToe. I wrote a working version based on what I know about scala, but noticed it was mostly imperative and my classes were mutable.

I'm going through and trying to implement some functional idioms and have managed to at least make the classes representing the game state immutable. However, I'm left with a class responsible for performing the game loop relying on mutable state and imperative loop as follows:

  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)      
    }
  }

What would be a more idiomatic way to program what I'm doing imperatively in this loop?

Full source code is here https://github.com/whaley/TicTacToe-in-Scala/tree/master/src/main/scala/com/jasonwhaley/tictactoe

like image 292
whaley Avatar asked Dec 09 '22 04:12

whaley


1 Answers

imho for Scala, the imperative loop is just fine. You can always write a recursive function to behave like a loop. I also threw in some pattern matching.

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)
}

Suppose we had a function whileSome : (a -> Option[a]) a -> (), which runs the input function until its result is None. That would strip away a little boilerplate.

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)
}

whileSome should be trivial to write; it is simply an abstraction of the former pattern. I'm not sure if it's in any common Scala libs, but in Haskell you could grab whileJust_ from monad-loops.

like image 165
Dan Burton Avatar answered Dec 14 '22 23:12

Dan Burton