2016-01-05 29 views
11

我在main.swift下面的代碼:GKMinmaxStrategist不返回任何動作

let strategist = GKMinmaxStrategist() 
strategist.gameModel = position 
strategist.maxLookAheadDepth = 1 
strategist.randomSource = nil 

let move = strategist.bestMoveForActivePlayer() 

...其中position是我GKGameModelPosition的一個實例。此代碼運行後,movenilbestMoveForPlayer(position.activePlayer!)也導致nil(但position.activePlayer!產生Player對象)。

然而,

let moves = position.gameModelUpdatesForPlayer(position.activePlayer!)! 

導致的可能的移動的非空數組。從蘋果公司的文件(約bestMoveForPlayer(_:)):

返回nil,如果玩家是無效的,玩家是不是遊戲模型的一部分,或者玩家沒有有效的可用的移動。

據我所知,沒有這種情況,但函數仍然返回nil。這裏會發生什麼?

如果它可以是任何幫助,這是我實現GKGameModel協議:

var players: [GKGameModelPlayer]? = [Player.whitePlayer, Player.blackPlayer] 
var activePlayer: GKGameModelPlayer? { 
    return playerToMove 
} 

func setGameModel(gameModel: GKGameModel) { 
    let position = gameModel as! Position 
    pieces = position.pieces 
    ply = position.ply 
    reloadLegalMoves() 
} 

func gameModelUpdatesForPlayer(thePlayer: GKGameModelPlayer) -> [GKGameModelUpdate]? { 
    let player = thePlayer as! Player 
    let moves = legalMoves(ofPlayer: player) 
    return moves.count > 0 ? moves : nil 
} 

func applyGameModelUpdate(gameModelUpdate: GKGameModelUpdate) { 
    let move = gameModelUpdate as! Move 
    playMove(move) 
} 

func unapplyGameModelUpdate(gameModelUpdate: GKGameModelUpdate) { 
    let move = gameModelUpdate as! Move 
    undoMove(move) 
} 

func scoreForPlayer(thePlayer: GKGameModelPlayer) -> Int { 
    let player = thePlayer as! Player 
    var score = 0 
    for (_, piece) in pieces { 
     score += piece.player == player ? 1 : -1 
    } 
    return score 
} 

func isLossForPlayer(thePlayer: GKGameModelPlayer) -> Bool { 
    let player = thePlayer as! Player 
    return legalMoves(ofPlayer: player).count == 0 
} 

func isWinForPlayer(thePlayer: GKGameModelPlayer) -> Bool { 
    let player = thePlayer as! Player 
    return isLossForPlayer(player.opponent) 
} 

func copyWithZone(zone: NSZone) -> AnyObject { 
    let copy = Position(withPieces: pieces.map({ $0.1 }), playerToMove: playerToMove) 
    copy.setGameModel(self) 
    return copy 
} 

如果有任何其他的代碼,我應該表現,讓我知道。

+0

你試過增加** maxLookAheadDepth **嗎? –

+0

我有,但它沒有區別。 –

+0

我有一個理論,可否請您添加您的playMove()實現來查看我的理論是否正確? –

回答

2

您需要更改申請取消應用一招activePlayer後。 在你的情況下,這將是playerToMove

該輪到的玩家將執行遊戲模型的更新。 GKMinmaxStrategist假定對applyGameModelUpdate:方法的下一次調用將代表該播放器進行移動。

,當然:

功能applyGameModelUpdate應用一個GKGameModelUpdate到遊戲的模型,可能導致新的activePlayer。 GKMinmaxStrategist會在主遊戲模型的副本上調用此方法來推測未來可能的移動及其影響。假設調用此方法代表由activePlayer屬性標識的播放器進行移動。

func applyGameModelUpdate(gameModelUpdate: GKGameModelUpdate) { 
    let move = gameModelUpdate as! Move 
    playMove(move) 

    //Here change the current Player 
    let player = playerToMove as! Player 
    playerToMove = player.opponent 
} 

同樣爲您unapplyGameModelUpdate實現。

此外,請特別注意您的setGameModel實施,因爲它應該在您的模型中複製所有數據。這包括activePlayer

設置另一個遊戲模型的數據。所有的數據都應該被複制,並且不應該維護指向複製遊戲狀態的指針。GKMinmaxStrategist使用它來處理遊戲的排列,而無需對主遊戲模型應用潛在的破壞性更新。

+0

我的'playMove(_ :)'函數確實改變了'playerToMove'(或者更具體地說,它增加了在'playerToMove'的getter中使用的'ply'變量)。 –

+0

我不知道爲什麼我以前沒有嘗試過,但是我在我的問題中顯示的八個函數中設置了斷點,並且'bestMoveForActivePlayer()'不調用它們中的一個。它只調用「activePlayer」的getter,兩次(這是兩次的第一個玩家)。 –

0

我有同樣的問題。結果,.activePlayer必須返回由.players返回的實例中的一個。返回一個匹配爲.playerId的新實例是不夠的。