2011/05/23

GreedyPlayer

ルールを覚えたてのときの戦略である、次の手を考えたときに、もっとも多くのマーカーがひっくり返せるところに打つプレイヤーを作る。
abstract class GreedyPlayer[N <: Node[N]] extends Player[N] {

  override def play(ply: Int, node: N, last: Move): Move = {
    val moves = node.possibleMoves()
    var bestMove = List[Move]()
    var maxS = Int.MinValue
    for (m <- moves) {
      val n = node.play(m).get
      val s = score(n)
      if (s > maxS) {
        bestMove = List(m)
        maxS = s
      } else if (s == maxS) {
        bestMove = m :: bestMove
      }
    }
    bestMove(Random.nextInt(bestMove.length))
  }

  def score(node: N): Int

}

実は、GreedyPlayer自体はreversiに特化されていなくて、単純にscoreがもっともよくなる次の手を打つというものである。ここで、scoreはゲームによって異なるのでabstractにしてある。単純にコマの数の差をスコアにすると、次のようになる。
trait MarkersScore {
  var marker: Marker
  /**
   * Returns a score for the marker
   */
  def score(node: ReversiNode): Int = {
    val nums = node.board.numOfMarkers
    if (marker == Dark) nums(Dark) - nums(Light)
    else nums(Light) - nums(Dark)
  }
}

RandomPlayerと1000番勝負をしてみると、Greedyが先手(D)で
D: 616, L: 349, -: 35
後手(L)で
D: 398, L: 567, -: 35
と、ちょっと強い程度。

2011/06/25: コード更新

0 件のコメント:

コメントを投稿