You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift版井字棋应用电脑获胜时胜利计数异常问题求助

井字棋人机对战胜利计数异常问题

问题描述

开发Swift井字棋应用时出现以下异常:

  • 双人对战模式下,玩家胜利计数逻辑正常
  • 人机对战模式下,电脑获胜后其胜利数始终停留在0,无法正确递增
  • 怀疑问题出在checkForWinner()函数或人机对战场景的胜利计数逻辑

问题原因分析

1. 错误的提前返回逻辑阻断胜负检测

在checkForWinner()函数开头存在以下代码:

if GameSettings.shared.playAgainstComputer && currentPlayer == 2 {
    if !boardArray.contains("") {
        return "It's a tie!"
    }
    return nil
}

该逻辑会直接跳过后续胜负检测流程:当人机对战且当前回合是电脑(玩家2)时,无论是否达成获胜条件,都会返回nil,导致电脑获胜的情况无法被识别。

2. 依赖currentPlayer判断获胜方的逻辑错误

在胜负检测分支中,人机对战模式下的计数逻辑依赖currentPlayer判断:

// X获胜分支
if GameSettings.shared.playAgainstComputer {
    if currentPlayer == 1 {
        countPlayer1 += 1
    }
}
// O获胜分支
if GameSettings.shared.playAgainstComputer {
    if currentPlayer == 2 {
        countPlayer2 += 1
    }
}

但在buttonTapped()流程中,落子完成后会立刻调用switchPlayers()切换玩家。当电脑(玩家2)落子完成后,currentPlayer已被切换为1,此时判断currentPlayer == 2必然不成立,导致countPlayer2无法递增。

修复方案

1. 移除错误的提前返回逻辑

删除checkForWinner()函数开头的以下代码块:

if GameSettings.shared.playAgainstComputer && currentPlayer == 2 {
    if !boardArray.contains("") {
        return "It's a tie!"
    }
    return nil
}

2. 修改获胜计数逻辑,直接根据棋子对应玩家

不再依赖currentPlayer,而是根据获胜的棋子类型(X/O)直接对应计数:

  • X对应玩家1,直接递增countPlayer1
  • O对应玩家2(电脑),直接递增countPlayer2

修复后的checkForWinner()函数:

func checkForWinner() -> String? {
    let winningPatterns: [[Int]] = [
        [0, 1, 2], [3, 4, 5], [6, 7, 8],
        [0, 3, 6], [1, 4, 7], [2, 5, 8],
        [0, 4, 8], [2, 4, 6]
    ]
    
    for pattern in winningPatterns {
        let positions = pattern.map { boardArray[$0] }
        if positions == ["X", "X", "X"] {
            countPlayer1 += 1
            return "Congrats \(playerOneName ?? "X"), you won!"
        } else if positions == ["O", "O", "O"] {
            countPlayer2 += 1
            return "Congrats \(playerTwoName ?? "O"), you won!"
        }
    }
    
    if boardArray.contains("") {
        return nil
    } else {
        return "Oh, it's a beautiful tie!"
    }
}

3. 优化配置项访问(可选)

GameViewController中缓存的playAgainstComputer属性可能存在过期风险,建议直接访问单例的实时值,替换所有self.playAgainstComputer为GameSettings.shared.playAgainstComputer。

最佳实践建议

  • 避免依赖切换后的玩家状态判断胜负:落子完成后会立刻切换玩家,此时currentPlayer代表下一个回合的玩家,而非刚完成落子的玩家,应通过落子的棋子类型直接关联对应的玩家计数。
  • 不要在胜负检测中加入无关的提前返回逻辑:提前返回会导致部分场景的胜负判断被跳过,需保证所有可能的获胜/平局情况都能被完整检测。
  • 单例配置项直接访问:对于全局配置的单例对象,直接访问其属性而非缓存值,避免因配置更新导致的逻辑异常。

内容的提问来源于stack exchange,提问作者AranAli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 19:15:54