In this homework, you will implement some functionality which will allow you to design a completely functional 5-in-a-row AI. The latter will be part of homework 4.
The game:
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...
X
is encoded as the first player (One
), and 0
, as Two
.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. This makes the code slightly easier to write, however Empty
cannot be seen as a valid player.
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:
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 (x,y)
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 the 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] = ???