Improving my Tic Tac Toe Solution in Scala I'm relatively new to Scala and made a small TicTacToe in a functional Style.
Any improvement options would be highly appreciated.
There are some things which I am unsure of if they are made in an optimal way.

Error Handling in the readMove Function
If i should incorporate types like (type Player = Char, type Field = Int) and if they would benefit the code
The printBoard function looks unclean and I can't yet figure out how to best change it.
board(nextMove) = nextPlayer(board) seems to break the style of immutable values.

This is already an improvement from my first version

import scala.annotation.tailrec
import scala.io.StdIn.readLine

object TicTacToeOld {
  val startBoard: Array[Char] = Array('1', '2', '3', '4', '5', '6', '7', '8', '9')
  val patterns: Set[Set[Int]] = Set(
    Set(0, 1, 2),
    Set(3, 4, 5),
    Set(6, 7, 8),
    Set(0, 3, 6),
    Set(1, 4, 7),
    Set(2, 5, 8),
    Set(0, 4, 8),
    Set(2, 4, 6)
  )

  def main(args: Array[String]): Unit = {
    startGame()
  }

  def startGame(): Unit ={
    println(&quot;Welcome to TicTacToe!&quot;)
    println(&quot;To play, enter the number on the board where you want to play&quot;)
    printBoard(startBoard)
    nextTurn(startBoard)
  }

  @tailrec
  private def nextTurn(board: Array[Char]): Unit = {
    val nextMove = readMove(board)
    board(nextMove) = nextPlayer(board)
    printBoard(board)
    if (!isWon(board)) {
      nextTurn(board)
    }
  }

  @tailrec
  private def readMove(board: Array[Char]): Int ={
    try {
      val input = readLine(&quot;Input next Turn: &quot;).toInt-1
      if(input&lt;0 || input&gt;8 || !board(input).toString.matches(&quot;[1-9]&quot;)) {
        throw new Exception
      }
      input
    } catch {
      case _: Exception =&gt; readMove(board)
    }
  }

  private def nextPlayer(board: Array[Char]): Char = {
    val remainingTurns = board.count(_.toString.matches(&quot;[1-9]&quot;))
    if(remainingTurns%2 == 0) 'x' else 'o'
  }

  private def printBoard(board: Array[Char]): Unit = {
    print(
      0 to 2 map { r =&gt;
        0 to 2 map { c =&gt;
          board(c + r*3)
        } mkString &quot;|&quot;
      } mkString (&quot;__________\n&quot;, &quot;\n------\n&quot;, &quot;\n&quot;)
    )
    println(&quot;Next Player is &quot; + nextPlayer(board))
  }
  
  private def isWon(board: Array[Char]): Boolean = {
    patterns.foreach(pattern=&gt;{
      if(pattern.forall(board(_) == board(pattern.head))) {
        print(&quot;Winner is &quot; + board(pattern.head))
        return true
      }
    })
    false
  }
}
you can remove main method and use extends App. It's safe 3 line of code.
replace Array('1', '2', '3', '4', '5', '6', '7', '8', '9') on ('1' to '9').toArray
I prefer always use type annotation if it is not clear. E.g.: val nextMove: Int = readMove(board)
use Intellij autoformat (ctrl + alt + L)
it is good idea to say user what is wrong with his input before prompt new one
[Char].toString.matches(&quot;[1-9]&quot;) may be replaced on [Char].isDigit (PS: may be it is not correct, because 0 is also digit)
don't use return keyword, especially in foreach, map and so on. It is not what you want, at least in this cases. foreach + forall + return should be replaced on contains + forall or something.
usually list map f used only for non-chained calls, but not for list map m filter filter collect g, because it is unclear for reader. UPDATE: also this syntax used for symbol-named functions, like +, ::, ! (in akka).
you can use special type for positive digit, for example, case class PosDigit(v: Int) {require(v &gt;= 0 &amp;&amp; v &lt;= 9, s&quot;invalide positive digit: $v&quot;)}
there is no essential reason to pass board as argument. Commonly if argument is passed, it is not changed. In your code it is not.

UPDATE for 10. In functional programming the clear way is to pass immutable collection to function and return new one if you need. It is programming without side effects. In OOP there is way to use mutable collection of class (or class's object). Scala both OOP and FP language.
Sorry for my English.