25.8. Ruchy komputera

Mając sposób oceny sytuacji na planszy można zbudować algorytm wybierający następny ruch do wykonania przez komputer. Prostym algorytmem wybierającym ruch — niekorzystającym nawet z możliwości oceny sytacji — mogłoby być losowe wybranie dowolnego spośród poprawnych ruchów. Jednak program używający takiego algorytmu nie sprawiałby wrażenia, że potrafi grać w szachy, a co najwyżej, że znane mu są przepisy gry. W opisywanym programie jest zaimplementowany trochę bardziej inteligentny algorytm, choć i tak jest on dosyć prymitywny i łatwy do ogrania. Algorytm wyboru ruchu jest zaimplementowany w pliku ComputerPlayer.scala, który zawiera definicję klasy ComputerPlayer i jej obiektu towarzyszącego.

Plik ComputerPlayer.scala:
package chess

import language.implicitConversions

object ComputerPlayer {

  def chooseRandomly(moves: Seq[Game]) = {
    import scala.util.Random
    if (moves.isEmpty) None
    else Some(moves(Random.nextInt(moves.size)))
  }

  implicit def Game2ComputerPlayer(game: Game): ComputerPlayer =
    new ComputerPlayer(game)

}

class ComputerPlayer(game: Game) {
  import ComputerPlayer._
  import Rank._

  def moves: Seq[Game] = {
    val moves = game.validGames.toList
    if (moves.isEmpty) Seq()
    else {
      val rankedMoves = moves.map(g => (g, g.rank(game.color)))
      val rankedMovesSorted = rankedMoves.sortBy(- _._2)
      val firstRank = rankedMovesSorted.head._2
      rankedMovesSorted.takeWhile(_._2 == firstRank).map(_._1)
    }
  }

  def makeMove = chooseRandomly(moves)

}

Do wyboru następnego ruchu służy metoda makeMove, wywołująca metodę chooseRandomly, podająca jej w argumencie rezultat wywołania metody moves. Metoda moves wybiera najlepsze spośród możliwych do wykonania ruchów, wykorzystując do oceny sytuacji metodę rank. Metoda chooseRandomly wybiera losowo jeden z nich.

scala> import chess._, ComputerPlayer._
import chess._
import ComputerPlayer._

scala> GameStart.moves.size
res1: Int = 4

Poniższa sesja w konsoli języka Scala pokazuje początek przykładowej partii rozgrywanej przez komputer sam ze sobą.

scala> val g1 = GameStart.makeMove
g1: Option[chess.Game] =
Some(Last move: White d2 to d4
 abcdefgh
8RNBQKBNR8
7PPPPPPPP7
6........6
5........5
4...p....4
3........3
2ppp.pppp2
1rnbqkbnr1
 abcdefgh)

scala> val g2 = g1.get.makeMove
g2: Option[chess.Game] =
Some(Last move: Black d7 to d5
 abcdefgh
8RNBQKBNR8
7PPP.PPPP7
6........6
5...P....5
4...p....4
3........3
2ppp.pppp2
1rnbqkbnr1
 abcdefgh)

scala> val g3 = g2.get.makeMove
g3: Option[chess.Game] =
Some(Last move: White c1 to e3
 abcdefgh
8RNBQKBNR8
7PPP.PPPP7
6........6
5...P....5
4...p....4
3....b...3
2ppp.pppp2
1rn.qkbnr1
 abcdefgh)

scala> g3.get.makeMove
res2: Option[chess.Game] =
Some(Last move: Black c8 to e6
 abcdefgh
8RN.QKBNR8
7PPP.PPPP7
6....B...6
5...P....5
4...p....4
3....b...3
2ppp.pppp2
1rn.qkbnr1
 abcdefgh)

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.