我的main.swift
中有以下代码:
let strategist = GKMinmaxStrategist()
strategist.gameModel = position
strategist.maxLookAheadDepth = 1
strategist.randomSource = nil
let move = strategist.bestMoveForActivePlayer()
...其中position
是我的GKGameModel
子类Position
的实例。运行此代码后,move
为nil
。 bestMoveForPlayer(position.activePlayer!)
也会产生nil
(但position.activePlayer!
会产生Player
个对象。
然而,
let moves = position.gameModelUpdatesForPlayer(position.activePlayer!)!
导致非空数组的可能移动。从Apple的文档(约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 :(得分:3)
您需要在应用或取消应用移动后更改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使用它来处理游戏的排列,而无需对主要游戏模型应用潜在的破坏性更新。
答案 1 :(得分:0)
我遇到了同样的问题。事实证明,.activePlayer
必须返回.players
返回的其中一个实例。仅返回匹配.playerId
的新实例是不够的。
答案 2 :(得分:0)
简单的清单:
.bestMove(for:)
被调用.gameModel
已设置isWin(for:)
未在移动前返回 trueisLoss(for:)
未在移动前返回 truegameModelUpdates(for:)
不会一直返回 nilscore(for:)
已实现