25.2. Kolory, figury i pola

W grze w szachy bierze udział dwójka graczy, z których jeden gra figurami białymi, a drugi czarnymi. W pliku Color.scala znajdują się definicje klasy Color oraz obiektów White i Black, reprezentujących oba kolory.

Plik Color.scala:
package chess

abstract sealed class Color {
  def other: Color
  def firstRow: Int
}

case object White extends Color {
  def other = Black
  def firstRow = 1
}

case object Black extends Color {
  def other = White
  def firstRow = 8
}

Pliki źródłowe umieścimy w podkatalogu src/main/scala naszego projektu. Jest to jedno z miejsc, w którym sbt standardowo szuka plików źródłowych języka Scala. Poleceniem compile możemy skompilować nasz plik (przy okazji sbt pobiera kolejne potrzebne zależności).

> compile
[info] Updating {file:/H:/jps2/examples/chess/}chess...
[info] Resolving org.sonatype.oss#oss-parent;7 ...
[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-library/2.11.7/scala-library-2.11.7.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-library;2.11.7!scala-library.jar (21821ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-compiler/2.11.7/scala-compiler-2.11.7.jar ...
…
[info] Done updating.
[info] Compiling 1 Scala source to H:\jps2\examples\chess\target\scala-2.11\classes...
[info] 'compiler-interface' not yet compiled for Scala 2.11.7. Compiling...
[info]   Compilation completed in 53.443 s
[success] Total time: 171 s, completed 2016-02-26 13:35:41
>

Z sesji sbt możemy uruchomić sesję konsoli języka Scala za pomocą polecenia console.

> console
[info] Starting scala interpreter...
[info]
Welcome to Scala version 2.11.7 (Java HotSpot(TM) Client VM, Java 1.8.0_05).
Type in expressions to have them evaluated.
Type :help for more information.

scala>

W klasie Color zadeklarowana jest metoda other, zaimplementowana w obu obiektach dziedziczących z tej klasy, która pozwala uzyskać dostęp do obiektu przeciwnego koloru.

scala> import chess._
import chess._

scala> White.other
res0: chess.Black.type = Black

scala> Black.other
res1: chess.White.type = White

Ponadto w tej klasie zadeklarowana jest metoda firstRow, zwracająca numer pierwszego wiersza planszy, z punktu widzenia określonego gracza.

scala> White.firstRow
res2: Int = 1

scala> Black.firstRow
res3: Int = 8

W grze w szachy używanych jest sześć różnych figur w każdym kolorze. Są to król (ang. King), hetman (ang. Queen), wieża (ang. Rook), goniec (ang. Bishop), skoczek (ang. Knight) oraz pion (ang. Pawn). Plik Figure.scala przedstawia w jaki sposób te figury są reprezentowane w programie.

Plik Figure.scala:
package chess

abstract sealed class FigureType
case object King extends FigureType
case object Queen extends FigureType
case object Rook extends FigureType
case object Bishop extends FigureType
case object Knight extends FigureType
case object Pawn extends FigureType

case class Figure(figureType: FigureType, figureColor: Color) {
  override def toString = (figureType, figureColor) match {
    case (King,   White) => "k"
    case (Queen,  White) => "q"
    case (Rook,   White) => "r"
    case (Bishop, White) => "b"
    case (Knight, White) => "n"
    case (Pawn,   White) => "p"
    case (King,   Black) => "K"
    case (Queen,  Black) => "Q"
    case (Rook,   Black) => "R"
    case (Bishop, Black) => "B"
    case (Knight, Black) => "N"
    case (Pawn,   Black) => "P"
  }
  def unicodeSymbol = (figureType, figureColor) match {
    case (King,   White) => "\u2654"
    case (Queen,  White) => "\u2655"
    case (Rook,   White) => "\u2656"
    case (Bishop, White) => "\u2657"
    case (Knight, White) => "\u2658"
    case (Pawn,   White) => "\u2659"
    case (King,   Black) => "\u265a"
    case (Queen,  Black) => "\u265b"
    case (Rook,   Black) => "\u265c"
    case (Bishop, Black) => "\u265d"
    case (Knight, Black) => "\u265e"
    case (Pawn,   Black) => "\u265f"
  }
}

Klasa FigureType i dziedziczące z niej obiekty reprezentują różne rodzaje figur szachowych. Klasa Figure reprezentuje natomiast figury określonego rodzaju i koloru. Figure jest klasą przypadku mającą elementy figureType i figureColor, reprezentujące właśnie rodzaj i kolor figury. Metoda toString tej klasy zwraca jednoliterowy napis odpowiadający danej figurze. Litera reprezentująca figurę to ta litera alfabetu, od jakiej rozpoczyna się angielska nazwa figury, z wyjątkiem skoczka, w którego przypadku wykorzystana jest druga litera, gdyż pierwsza jest taka sama, jak w przypadku króla. Figury białe reprezentowane są przez małe litery, a figury czarne przez duże. Metoda unicodeSymbol zwraca symbol Unicode odpowiadający danej figurze.

scala> Figure(King, White)
res0: chess.Figure = k
scala> Figure(King, Black)
res1: chess.Figure = K

scala> Figure(Knight, White)
res2: chess.Figure = n

Gra w szachy odbywa się na planszy mającej 64 pola. Plansza ma kształt kwadratu mającego osiem rzędów — oznaczanych numerami od 1 do 8 — i osiem kolumn — oznaczanych literami od a do h. W pliku Field.scala znajduje się definicja klasy Field, reprezentującej pole planszy.

Plik Field.scala:
package chess

case class Field(col: Int, row: Int) {
  override def toString = (col + 'a' - 1).toChar.toString + row
  def relative(c: Int, r: Int) = Field(col+c, row+r)
  def isLastRow(color: Color) = row == color.other.firstRow
  def isValid = col >= 1 && col <= 8 && row >= 1 && row <= 8
}

Klasa Field jest klasą przypadku mającą zdefiniowane dwa elementy, reprezentujące kolumnę i wiersz, czyli współrzędne pola na planszy. Każda ze współrzędnych mieści się w zakresie od 1 do 8. Metoda toString jest zdefiniowana w taki sposób, aby zwracać współrzędne pola w postaci litery określającej kolumnę i liczby określającej wiersz.

scala> Field(1,1)
res3: chess.Field = a1

scala> Field(2,1)
res4: chess.Field = b1

scala> Field(8,8)
res5: chess.Field = h8

Klasa Field posiada dodatkowe metody, które są wykorzystywane w innych fragmentach programu. Metoda relative zwraca nowe pole, mające współrzędne przesunięte w stosunku do danego pola o określoną liczbę kolumn i wierszy. Metoda isLastRow zwraca wartość logiczną informującą, czy dane pole należy do ostatniego rzędu z punktu widzenia określonego gracza. Metoda isValid zwraca wartość logiczną informującą, czy pole ma prawidłowe współrzędne, czyli czy należy do planszy.

scala> Field(2,3).relative(1,1)
res6: chess.Field = c4

scala> Field(2,3).relative(4,5)
res7: chess.Field = f8

scala> Field(7,8).isLastRow(Black)
res8: Boolean = false

scala> Field(7,1).isLastRow(Black)
res9: Boolean = true

scala> Field(2,2).isValid
res10: Boolean = true

scala> Field(0,2).isValid
res11: Boolean = false

Język programowania Scala Wydanie 2. Copyright © Grzegorz Balcerek 2016

Licencja Creative Commons

Ten utwór jest dostępny na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowe.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.