Console Tic-Tac-Toe Game
Build a tic-tac-toe game in Scala that two people play in the terminal, taking turns to type the cell where they want to place their X or O. The game prints the board after every move, refuses invalid moves, and announces the winner or a draw. What makes it a good Scala exercise is that the board never changes: each move creates a new board, which makes the code easier to reason about and test. You'll learn case classes, immutable collections such as Vector, Option and Either for handling invalid input without exceptions, pattern matching, recursion instead of loops, building with sbt, and testing with ScalaTest.
- Estimate
- ~7.5h
- Steps
- 5
- Completed by
- 0
- Proposed by
- codeseed.app
sbt · ScalaTest
Project roadmap
- 01
Set up the project and model the board
~1.5hCreate a project with sbt new scala/scala3.g8 and add ScalaTest. Model a Player (X or O) as an enum, and a Board case class wrapping a Vector of 9 cells, each an Option[Player] (None when empty). Add a method that returns the board as text with row and column numbers. Done when: printing an empty board shows a neat 3×3 grid.
- 02
Validate moves
~1.5hWrite a place(row, col, player) method returning Either[String, Board]: Left with a message when the position is outside 1 to 3 or the cell is taken, and Right with a new board otherwise (the old board is unchanged). Write a function that parses the player's input, such as 2 3, into a position, also returning Either. Done when: valid moves return a new board, and invalid ones return a clear message.
- 03
Detect wins and draws
~1.5hList the 8 winning lines (3 rows, 3 columns, 2 diagonals) as index triples, and write a winner method that checks them with pattern matching and returns Option[Player]. A draw is a full board with no winner. Model the game status as a sealed trait or enum: InProgress, Won(player) or Draw. Done when: every winning line and a draw are recognized correctly.
- 04
Build the game loop
~1.5hWrite the game as a recursive function taking the current board and player: print the board, ask for a move, and on invalid input show the message and ask again; on a valid move, check the status and either finish or call itself with the new board and the other player. Mark it @tailrec. Offer a new game at the end. Done when: two people can play complete games in the terminal.
- 05
Write tests
~1.5hWrite ScalaTest tests: placing on an empty cell, placing on a taken cell, out-of-range positions, input parsing (valid, letters, missing numbers), every winning line, a draw, and that placing a move never changes the original board. Done when: sbt test passes.
Resources
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack