In this homework, you will implement some functionality which will allow you to design a completely functional tic-tac-toe AI. The latter will be part of homework 4.

About Tic Tac Toe

Tic Tac Toe is usually played on a 3 by 3 board, marking positions by each player in rounds. Our game is slightly different:

  • it can be played on a square board of any size larger or equal to 5.
  • A player wins if it has marked a line, column or diagonal of 5 consecutive positions in a row.

Example of a winning position for X on a 5×5 board:

X...0
0X.0.
..X0.
...X.
.0..X

Example of a winning position for 0 on a 7×7 board:

.X...X.
...0...
...0...
.X.0..X
0..0..0
...0...
...X...

Coding conventions

  • In your project template, X is encoded as the first player (One), and 0, as Two.
  • A Board is encoded as a List of Lists of positions (i.e. a matrix), where a position can be One, Two or Empty. We make no distinction in the code between a position and a player, although Empty cannot be seen as a valid player. This makes the code slightly easier to write.

Coding tasks

1. Write a function which converts a string into a Board. As a helper, you can use _.split© where c is a separator string, and _.toList. The best solution is to use a combination of map calls with the above mentioned functions. A string is encoded exactly as in the examples shown above:

  • there are no whitespaces - empty positions are marked by the character '.'
  • lines are delimited by '\n' (the last line does not have a trailing '\n').
def makeBoard(s: String): Board = {
    def toPos(c: Char): Player =
      c match {
        case 'X' => One
        case '0' => Two
        case _ => Empty
      }
    ???

2. Write a function which checks if a position on the board is free. Recall that list indexing can be done using l(_). Positions are numbered from 0.

def isFree(x:Int, y:Int, b:Board):Boolean = ???

3. Write a function which returns the opponent of a player:

def complement(p: Player): Player =

4. Write a function which converts a board to a string, following the same strategy. Important: this function will be used throughout the tests. Make sure string doesn't end with '\n'. Hint: instead of foldRight, you can use reduce which works quite similarly, but without requiring an accumulator.

def show(b: Board): String = ???

5. Write a function which returns the columns of a board:

def getColumns(b:Board): Board = ???

6. Implement the following two functions for extracting the first and second diagonal, as lines, from a board. Hint: use for comprehensions.

def getFstDiag(b:Board): Line = ???
def getSndDiag(b:Board): Line = ???

7. Implement the following functions for extracting diagonals above/below the first/second diagonal, as lines. It's not really necessary to make sure that at least 5 positions are available, for now. Hint: if one function must be implemented with element-by-element iteration, the three other can be implemented using each-other, as single-line calls.

def getAboveFstDiag(b: Board): List[Line] = ???
def getBelowFstDiag(b: Board): List[Line] = ???
def getAboveSndDiag(b: Board): List[Line] = ???
def getBelowSndDiag(b: Board): List[Line] = ???

8. Write a function which checks if a player is the winner. Hint: functions l.forall(_) and l.exists(_) may be very helpful, together with patterns.

def winner(p: Player)(b: Board): Boolean = 

9. Write a function which updates a position from the board, with a given player. The position need not be empty and you are not required to check this. Hint: re-use an inner aux-function together with take and drop.

def update(p: Player)(ln: Int, col: Int, b: Board) : Board = ??? 

10. Write a function which generates all possible next-moves for any of the two players. A next-move consists in a new board, where the player-at-hand played his move. The order in which you generate next-moves is not important.

def next(p: Player)(b: Board): List[Board] = ???

Project format

  • You should not change any other files of the project, except for the template-file. For this homework, the template-file is Main.scala. Warning: if a submission has changes in other files, it may not be graded.
  • To solve your homework, download the Homework project and rename it using the following convention: HX_<LastName>_<FirstName>, where X is the homework number. (Example: H3_Popovici_Matei). If your project name disregards this convention, it may not be graded.
  • Each project file contains a profileID definition which you must fill out with your token ID received via email for this lecture. Make sure the token id is defined correctly. (Grades will be automatically assigned by token ID).
  • In order to be graded, the homework must compile. If a homework has compilation errors (does not compile), it will not be graded. Please take care to remove code that does not compile by replacing (or keeping) function bodies implemented with ???.

Submission

  • Your submission should be an archived file with your solved project, named via the convention specified previously.
  • All homework must be submitted via moodle. Submissions sent via email will not be graded!.
  • All homework must be submitted before the deadline. Submissions that miss the deadline (even by minutes) will not be graded. (All deadlines will be fixed at 8:00 AM, so that you can take advantage of an all-nighter, should you choose to).

Points

  • Points are assigned for each test (for a total of 100p), but the final grade will be assigned after manual review. Selectively, a homework may be required to be presented during lab for the final grade.

Integrity

  • Each homework uses public test-cases which you can use to guide and test your implementation. Most test-cases are simple, in order to be as easy to use as possible. If an implementation is written with the sole purpose of passing those specific tests, thus disregarding the statement, the entire homework will not be graded!
  • The homework must be solved individually - you are not allowed to share or to take code from other sources including the Internet.

We strongly encourage you to ask questions via the forum (instead of MS Teams) so that other students can benefit from the answers and discussion. You may ask questions about the homework during lab. You will receive feedback about your implementation ideas, but not on the actual written code.