我仍然在學習Scala,並決定實施一個黑白棋遊戲。我使用Alpha Beta修剪,基於這個algorithm來實現AI組件。優化Scala代碼片段
但是我意識到我的執行效率不高。如果我將算法的最大深度增加到5以上,我會開始注意性能問題。我意識到搜索空間是指數級的,所以我希望能夠幫助我指出優化此代碼的方法。
下面是如何實現的算法:
trait MaxMin
case class Max() extends MaxMin
case class Min() extends MaxMin
object AlphaBeta {
type Move = List[State]
type FitnessMove = Tuple2[Int, List[Move]]
def not(p: Player) = p match {
case _: Player2 => Player1()
case _: Player1 => Player2()
}
def max(x: FitnessMove, y: FitnessMove) = if (x._1 >= y._1) x else y
def min(x: FitnessMove, y: FitnessMove) = if (x._1 <= y._1) x else y
def terminal(turn: Int) = if (turn >= 64) true else false
def search(board: Board, player: Player, turn: Int, MAX_DEPTH: Int = 5): Move = {
def alphaBeta(node: Board, depth: Int, alpha: Int, beta: Int,
moveChoice: List[Move], player: Player, p: MaxMin, turn: Int): FitnessMove =
if (depth == 0 || terminal(turn))
(player.evalHeuristic(node, turn), moveChoice)
else
p match {
case _: Max =>
player.getPossibleMoves(node).
takeWhile(_ => beta > alpha). // Pruning
foldLeft((alpha, moveChoice)) { case ((alpha, moveChoice), move) =>
val simulate = player.simulateMove(node, move)
max((alpha, moveChoice),
alphaBeta(simulate, depth-1, alpha, beta,
move :: moveChoice, not(player), Min(), turn+1))
}
case _: Min =>
player.getPossibleMoves(node).
takeWhile(_ => beta > alpha). // Pruning
foldLeft((beta, moveChoice)) { case ((beta, moveChoice), move) =>
val simulate = player.simulateMove(node, move)
(
min((beta, moveChoice),
alphaBeta(simulate, depth-1, alpha, beta,
moveChoice, not(player), Max(), turn+1))._1,
moveChoice
)
}
}
val (_, moveChoice) = alphaBeta(board, MAX_DEPTH, Integer.MIN_VALUE, Integer.MAX_VALUE, List.empty[Move], player, Max(), turn)
if (!moveChoice.isEmpty) moveChoice.head
else player.getPossibleMoves(board).head
}
}
,如果我使用while循環和一個更加「勢在必行」的做法,但我更願意保持不變的代碼,我大概可以得到更好的性能。我可以在代碼上做出什麼改進,或者你會以不同方式處理整個算法的實現?
這是game如果你想檢查出來。謝謝!
只是如果你是感興趣:前段時間我寫了一個基於小控制檯的Othello實現,沒有AI:https://gist.github.com/sschaef/2472666 – sschaef 2013-03-17 01:04:33
你能否確保你附加一個測試,以便我可以自由地重構你的代碼而不會中斷其功能? – Edmondo1984 2013-03-17 02:45:24
嗨@ Edmondo1984是的,我會嘗試儘快添加一些測試。 – 2013-03-17 19:49:54