15

我的代码中有以下代码main.swift

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

let move = strategist.bestMoveForActivePlayer()

...我的子类position的一个实例在哪里。运行此代码后,是. 也会导致(但会导致对象)。GKGameModelPositionmovenilbestMoveForPlayer(position.activePlayer!)nilposition.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
}

如果我应该显示任何其他代码,请告诉我。

4

3 回答 3

4

您需要更改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 使用它来处理游戏的排列,而无需对主要游戏模型应用具有潜在破坏性的更新。

于 2016-01-12T20:24:35.180 回答
0

我有同样的问题。事实证明,.activePlayer必须返回由返回的实例.players之一。仅返回一个带有匹配的新实例是不够的.playerId

于 2016-09-11T15:42:25.647 回答
0

简单的清单:

  1. GKMinmaxStrategist.bestMove(for:)被称为
  2. GKMinmaxStrategist 的.gameModel设置
  3. GKGameModelisWin(for:)在移动前不返回 true
  4. GKGameModelisLoss(for:)在移动前不返回 true
  5. GKGameModelgameModelUpdates(for:)不会一直返回 nil
  6. GKGameModel 的score(for:)实现
于 2021-07-05T17:47:10.630 回答