Skip to content

Instantly share code, notes, and snippets.

@Reldan
Created April 16, 2014 08:49
package com.daggerfrog.luxoft
object PiecesSet {
val pieces = Set(Empty, Threated, King, Queen, Rook, Bishop, Knight)
val fromByte = pieces.map(el ⇒ el.byteRepr → el).toMap
val fromChar = pieces.map(el ⇒ el.charRepr → el).toMap
def char2Byte(el: Char) = fromChar(el).byteRepr
def byte2Char(el: Byte) = fromByte(el).charRepr
}
trait Cell {
def charRepr: Char
def byteRepr: Byte
}
trait Piece extends Cell {
protected def threatedNotSafe(x: Int, y: Int, height: Int, width: Int): Iterable[(Int, Int)]
def place(x: Int, y: Int, height: Int, width: Int) =
crop(height, width, threatedNotSafe(x, y, height, width))
private def crop(height: Int, width: Int, data: Iterable[(Int, Int)]) =
data.filter { case(nX, nY) ⇒ nX >= 0 && nX < width && nY >= 0 && nY < height }
}
object Empty extends Cell {
val charRepr = '#'
def byteRepr = 0
}
object Threated extends Cell {
val charRepr = '*'
def byteRepr = 1
}
object King extends Piece {
val charRepr = 'K'
def byteRepr = 2
override def threatedNotSafe(x: Int, y: Int, height: Int, width: Int) =
for (xShift ← Range(-1, 2); yShift ← Range(-1, 2))
yield (xShift + x, yShift + y)
}
object Queen extends Piece {
val charRepr = 'Q'
def byteRepr = 3
override def threatedNotSafe(x: Int, y: Int, height: Int, width: Int) =
Bishop.threatedNotSafe(x, y, height, width) ++ Rook.threatedNotSafe(x, y, height, width)
}
object Rook extends Piece {
val charRepr = 'R'
def byteRepr = 4
override def threatedNotSafe(x: Int, y: Int, height: Int, width: Int) =
Range(0, height).map(i ⇒ (x, i)) ++ Range(0, width).map(i ⇒ (i, y))
}
object Bishop extends Piece {
val charRepr = 'B'
def byteRepr = 5
override def threatedNotSafe(x: Int, y: Int, height: Int, width: Int) =
Range(1, y + 1).flatMap(i => List((x - i, y - i), (x + i, y - i))) ++
Range(1, height - y).flatMap(i ⇒ List((x - i, y + i), (x + i, y + i)))
}
object Knight extends Piece {
val charRepr = 'k'
def byteRepr = 6
override def threatedNotSafe(x: Int, y: Int, height: Int, width: Int) =
List((2, 1), (2, -1), (-2, 1), (-2, -1), (1, 2), (1, -2), (-1, -2), (-1, 2)).map{
case(xShift, yShift) ⇒ (xShift + x, yShift + y)
}
}
object ChessBoard {
def create(height: Int, width: Int) = {
ChessBoard(height, width, new Array[Byte](height * width))
}
}
case class ChessBoard private (height: Int, width: Int, board: Array[Byte]) {
require(height * width == board.size)
override def toString = {
board.map(PiecesSet.byte2Char).mkString.grouped(width).mkString("\n")
}
private def flatDim(point: (Int, Int)): Int = flatDim(point._1, point._2)
private def flatDim(x: Int, y: Int): Int = x + y * width
def placePieces(pieces: Iterable[Piece]): Int = {
if (pieces.isEmpty) {
1
}
else
Range(0, width).foldLeft(0){
case(acc, x) ⇒ acc + Range(0, height).foldLeft(0) {case(acc, y) ⇒
acc + placePiece(x, y, pieces.head).map(_.placePieces(pieces.tail)).getOrElse(0)
}
}
}
def placePiece(x: Int, y: Int, piece: Piece): Option[ChessBoard] = {
require(x < width)
require(y < height)
val index = flatDim((x, y))
if (PiecesSet.fromByte(board(index)) != Empty)
None
else {
val newThreated = piece.place(x, y, height, width)
val valid = newThreated.forall {
point ⇒
val cell = PiecesSet.fromByte(board(flatDim(point)))
cell == Empty || cell == Threated
}
if (!valid)
None
else {
val newBoard = board.clone()
newThreated.foreach(point ⇒ newBoard(flatDim(point)) = Threated.byteRepr)
newBoard(flatDim(x, y)) = piece.byteRepr
Some(ChessBoard(height, width, newBoard))
}
}
}
}
object ChessBoardApp extends App {
val board = ChessBoard.create(3, 3)
val pieces = List(Rook, King, King)
println(board.placePieces(pieces))
// println(board)
//
// val newBoard = board.placePiece(3, 2, Knight).get
//
//// println
// println(newBoard)
//// println
// println(newBoard.placePiece(9, 0, Bishop).get)
// println(newBoard.placePiece(1, 1, Bishop).get)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment