#swift #gameplay-kit #gkminmaxstrategist
#swift #игровой набор #gkminmaxstrategist
Вопрос:
Я работаю над настольной стратегической игрой для двух игроков с возможностью играть против процессора, и я использую GKMinmaxStrategist, чтобы дать немного мозгов игроку с процессором.Просто для справки, в игре есть две «фракции» (Король, Враг), и всегда начинается та, которая играет в Короля.
Теперь мне удалось внедрить стратегию, и она работает, если я играю королем против процессора и делаю первый ход. Однако, когда я играю за врага, а процессор должен сделать первый ход (играя за короля), это, как ни странно, не работает. Похоже, что после вызова метода bestMove стратега он не вызывает ни один из базовых методов моделирования, таких как isWin, apply, score и т. Д.
Я пытался изменить правила так, чтобы противник всегда начинал, но опять же это не сработало, в то время как он выдавал ходы за противника, когда я играл королем и делал первый ход (как упоминалось выше).
Кроме того, вместо использования стратега я просто выбирал ходы случайным образом (из всех возможных ходов), просто чтобы посмотреть, работает ли пошаговая логика, и это сработало. Для обеих фракций это происходит тогда, когда и как я бы этого ожидал.
Итак, этот первый шаг, независимо от того, для какой фракции он кажется проблемой, и я не могу понять, почему это так. Кто-нибудь сталкивался с подобной проблемой или у кого-нибудь есть какие-нибудь яркие идеи относительно того, почему это может быть так?
Любая помощь будет высоко оценена.
Это расширение игровой модели, включающее стратега, а также GameVC, который управляет игровым процессом.
extension Board: GKGameModel {
var activePlayer: GKGameModelPlayer? {
return currentPlayer
}
var players: [GKGameModelPlayer]? {
return Player.allPlayers
}
func copy(with zone: NSZone? = nil) -> Any {
let copy = Board()
copy.setGameModel(self)
return copy
}
func setGameModel(_ gameModel: GKGameModel) {
if let board = gameModel as? Board {
tokens = board.tokens
}
}
func isWin(for player: GKGameModelPlayer) -> Bool {
guard let player = player as? Player else {
return false
}
if let winner = isWinner() {
return player.player == winner
} else {
return false
}
}
func gameModelUpdates(for player: GKGameModelPlayer) -> [GKGameModelUpdate]? {
guard let player = player as? Player else {
return nil
}
if isWin(for: player) {
return nil
}
return allPossibleMoves(faction: player.player)
}
func apply(_ gameModelUpdate: GKGameModelUpdate) {
guard let move = gameModelUpdate as? Move else {
return
}
performMove(move: move)
currentPlayer = currentPlayer.opponent
}
func score(for player: GKGameModelPlayer) -> Int {
guard let player = player as? Player else {
return Score.none.rawValue
}
if isWin(for: player) {
return Score.win.rawValue
} else {
return Score.none.rawValue
}
}
}```
```class GameViewController: UIViewController, BoardDelegate {
var scene: GameScene!
var board: Board!
var strategist: GKMinmaxStrategist!
override func loadView() {
self.view = SKView(frame: UIScreen.main.bounds)
}
override func viewDidLoad() {
super.viewDidLoad()
let skView = view as! SKView
skView.isMultipleTouchEnabled = false
skView.isUserInteractionEnabled = false
scene = GameScene(size: skView.bounds.size)
scene.scaleMode = .aspectFill
board = Board()
board.delegate = self
scene.board = board
scene.handleUserMove = handleUserMove
scene.fillBoardWithSprites()
strategist = GKMinmaxStrategist()
strategist.maxLookAheadDepth = 1
strategist.randomSource = GKARC4RandomSource()
strategist.gameModel = board
skView.presentScene(scene)
initiateMove()
}
//Check if user`s turn
func checkUserTurn() -> Bool {
return board.userPlayer.player == board.currentPlayer.player
}
//Change turn of players between user and CPU
func changeTurn() {
board.currentPlayer = board.currentPlayer.opponent
}
//Find best move for CPU using GKMinmaxStrategist
func chooseCpuMove() -> Move? {
if let move = strategist.bestMove(for: board.currentPlayer) as? Move {
print("found move")
return move
}
return nil
}
//Perform CPU move
func handleCpuMove(move: Move) {
scene.animateMove(move: move) {}
board.performMove(move: move)
board.moved()
}
//Check whose turn it is and either turn on user interaction or start CPU move
func initiateMove() {
print("initiating")
self.view.isUserInteractionEnabled = checkUserTurn()
if checkUserTurn() {
//Wait for user to move
} else {
print("checking cpuMove")
if let cpuMove = chooseCpuMove() {
handleCpuMove(move: cpuMove)
}
}
}
func handleUserMove(move: Move, bool: Bool) {
if board.isMoveAllowed(move: move) {
scene.animateMove(move: move) {}
board.performMove(move: move)
board.moved()
}
}
func currentPlayerDidMove(board: Board) {
changeTurn()
if board.isWinner() != nil {
board.endGame()
} else {
DispatchQueue.main.asyncAfter(deadline: .now() 2.0) {
self.initiateMove()
}
}
}
func gameDidEnd(board: Board) {
self.view.isUserInteractionEnabled = false
UserDefaults.standard.set(board.currentPlayer.player.name, forKey: "winner")
AppDelegate.shared.rootViewController.gameOverScreen()
}
}```