oopuebung/uebung01/Chess.scala
2025-04-14 23:08:06 +02:00

162 lines
5.5 KiB
Scala

package oop.ch01.chess.scala
import oop.ch01.chess.scala.Color.{black, white}
import oop.ch01.chess.scala.Kind.rook
import scala.collection.mutable.ArrayBuffer
enum Color:
case black, white
enum Kind:
case queen, knight, rook
class Piece(var kind: Kind,
var color: Color,
var board: Board,
var row: Int,
var col: Int)
class Board(var pieces: List[Piece])
object Chess:
def newPiece(kind: Kind, color: Color,
board: Board, row: Int, col: Int): Piece =
if row < 1 || row > 8 || col < 1 || col > 8 then
throw new IllegalArgumentException("Invalid pos " + row + "/" + col)
val piece = new Piece(kind, color, board, row, col)
add(board, piece)
piece
def charRep(piece: Piece): Char = piece.kind match
case Kind.queen => queenCharRep(piece)
case Kind.knight => knightCharRep(piece)
case Kind.rook => rookCharRep(piece)
def toString(piece: Piece): String = piece.kind match
case Kind.queen => queenToString(piece)
case Kind.knight => knightToString(piece)
case Kind.rook => rookToString(piece)
def canCapture(piece: Piece, other: Piece): Boolean = piece.kind match
case Kind.queen => queenCanCapture(piece, other)
case Kind.knight => knightCanCapture(piece, other)
case Kind.rook => rookCanCapture(piece, other)
def queenCharRep(piece: Piece): Char =
if piece.color == Color.white then 'q' else 'Q'
def knightCharRep(piece: Piece): Char =
if piece.color == Color.white then 'n' else 'N'
def rookCharRep(piece: Piece): Char =
if piece.color == Color.white then 'r' else 'R'
def queenToString(piece: Piece): String =
"" + piece.color + " queen at (" + piece.row + ", " + piece.col + ")"
def knightToString(piece: Piece): String =
"" + piece.color + " knight at (" + piece.row + ", " + piece.col + ")"
def rookToString(piece: Piece): String =
"" + piece.color + " rook at (" + piece.row + ", " + piece.col + ")"
def queenCanCapture(queen: Piece, other: Piece): Boolean =
if queen.board != other.board || queen.color == other.color then
return false
if other.row != queen.row &&
other.col != queen.col &&
(other.row - queen.row).abs !=
(other.col - queen.col).abs then
return false
val dr: Int = (other.row - queen.row).sign
val dc: Int = (other.col - queen.col).sign
var r: Int = queen.row + dr
var c: Int = queen.col + dc
while r != other.row || c != other.col do
if pieceAt(queen.board, r, c) != null then
return false
r += dr
c += dc
true
def knightCanCapture(knight: Piece, other: Piece): Boolean =
if knight.board != other.board ||
knight.color == other.color then
return false
val dr: Int = (knight.row - other.row).abs
val dc: Int = (knight.col - other.col).abs
dr == 2 && dc == 1 || dr == 1 && dc == 2
def rookCanCapture(piece: Piece, other: Piece): Boolean =
if piece.board != other.board || piece.color == other.color then return false
if other.row != piece.row &&
other.col != piece.col then
return false
val dr: Int = (other.row - piece.row).sign
val dc: Int = (other.col - piece.col).sign
var r: Int = piece.row + dr
var c: Int = piece.col + dc
while r != other.row || c != other.col do
if pieceAt(piece.board, r, c) != null then
return false
r += dr
c += dc
true
def newBoard(): Board =
new Board(List())
def add(board: Board, piece: Piece): Unit =
if piece.board != board then
throw new IllegalArgumentException("wrong board")
val existing = pieceAt(board, piece.row, piece.col)
if existing != null then
throw new IllegalArgumentException("already occupied by " +
toString(existing))
piece.board.pieces = piece :: piece.board.pieces
def toString(board: Board): String =
//"pieces: " + board.pieces
"pieces: " + board.pieces.map(toString)
def printBoard(board: Board): Unit =
println(" 1 2 3 4 5 6 7 8")
println(" +---+---+---+---+---+---+---+---+")
for row: Int <- 1 to 8 do
print("" + row + " ")
for col: Int <- 1 to 8 do
val p: Piece = pieceAt(board, row, col)
val c: Char = if p == null then ' ' else charRep(p)
print("| " + c + " ")
println("|")
println(" +---+---+---+---+---+---+---+---+")
def pieceAt(board: Board, row: Int, col: Int): Piece =
for p: Piece <- board.pieces do
if p.row == row && p.col == col then
return p
null
def check(board: Board): Unit =
for p1: Piece <- board.pieces do
println(toString(p1))
for p2: Piece <- board.pieces if p1 != p2 do
if canCapture(p1, p2) then
println(" can capture " + toString(p2))
else
println(" cannot capture " + toString(p2))
def main(args: Array[String]): Unit =
val board: Board = newBoard()
val p1: Piece = newPiece(Kind.queen, Color.black, board, 1, 4)
val p2: Piece = newPiece(Kind.queen, Color.white, board, 8, 4)
val p3: Piece = newPiece(Kind.knight, Color.white, board, 3, 3)
val p4: Piece = newPiece(Kind.knight, Color.black, board, 6, 4)
val p5: Piece = newPiece(Kind.rook, white, board, 2,7)
val p6: Piece = newPiece(rook, black, board, 2,1)
println(board)
println(toString(board))
printBoard(board)
check(board)