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

iOS/Swift环境下基于NSRegularExpression的国际象棋记谱法匹配拆分与解析方案问询

处理国际象棋记谱的正则优化方案(iOS/Swift环境)

嘿,我之前在做国际象棋记谱解析的时候也碰到过一模一样的痛点——尤其是这种单步和回合走法对的歧义问题,给你分享一套在Swift里用NSRegularExpression搞定的思路,亲测好用:

核心问题拆解

你说的关键点太对了:除了最后一组走法,前面每个回合都是白方+黑方的配对,但单步正则根本没法直接区分,像Nd5e3这种既可能是“马从d5走到e3”的单步,又可能是“白方马到d5+黑方兵到e3”的回合对,纯靠单次正则匹配确实搞不定。

分步解决思路

1. 先拆回合,再拆走法对

我建议先把整个记谱按「回合号+走法串」拆分,比如先把5.Nd5e3e3拆成回合号5和走法串Nd5e3e3,这样我们可以把每个回合的走法单独处理,避免全局匹配的混乱。

2. 针对走法对的正则设计

这里的核心是抓住黑方走法的特征:黑方的兵走法是纯坐标(比如e3),其他棋子会带KQNBR大写字母;而白方走法要么带棋子字母,要么兵走法也是纯坐标,但它一定在黑方走法前面。

我整理了一个适配走法对的正则,先匹配白方走法,再匹配黑方走法(兼容黑方兵的纯坐标):

^(([KQNBR]?[a-h]?[1-8]?[a-h][1-8]))(([KQNBR]?[a-h]?[1-8]?[a-h][1-8])|([a-h][1-8]))$

逻辑很简单:

  • 第一组:匹配白方的任意合法走法(不管是带棋子的还是兵的纯坐标)
  • 第二部分:匹配黑方走法,要么是带棋子的完整走法,要么是兵的纯坐标

如果怕和回合号混淆,可以加个反向断言确保黑方走法前面不是数字:

^(([KQNBR]?[a-h]?[1-8]?[a-h][1-8]))((?<!\d)([KQNBR]?[a-h]?[1-8]?[a-h][1-8])|([a-h][1-8]))$

3. Swift里的具体实现

分两步走,代码都是可直接复用的:

第一步:提取每个回合的走法串

先把所有回合的结构匹配出来,拿到每个回合的走法内容:

let notation = "5.Nd5e3e3 6.Nf6g4d7 7.Qa1h8"
let roundRegex = try! NSRegularExpression(pattern: "(\\d+)\\.([A-Za-z0-9]+)", options: [])
let matches = roundRegex.matches(in: notation, options: [], range: NSRange(notation.startIndex..., in: notation))

for match in matches {
    let roundNumber = notation[Range(match.range(at: 1), in: notation)!]
    let movePairString = notation[Range(match.range(at: 2), in: notation)!]
    
    // 单独处理每个回合的走法对
    self.processMovePair(movePairString: String(movePairString), round: String(roundNumber))
}

第二步:拆分走法对为白黑走法

针对每个走法串,用我们的正则拆分,如果匹配失败,就说明是最后一个回合的单步走法(比如黑方认输,只有白方走法):

func processMovePair(movePairString: String, round: String) {
    let movePairRegex = try! NSRegularExpression(pattern: "^(([KQNBR]?[a-h]?[1-8]?[a-h][1-8]))(([KQNBR]?[a-h]?[1-8]?[a-h][1-8])|([a-h][1-8]))$", options: [])
    guard let match = movePairRegex.firstMatch(in: movePairString, options: [], range: NSRange(movePairString.startIndex..., in: movePairString)) else {
        // 处理单步走法的情况
        print("回合\(round):仅单步走法 \(movePairString)")
        return
    }
    
    let whiteMove = movePairString[Range(match.range(at: 1), in: movePairString)!]
    let blackMove = movePairString[Range(match.range(at: 3), in: movePairString)!]
    
    print("回合\(round):白方走法 \(whiteMove),黑方走法 \(blackMove)")
}

4. 歧义情况的额外校验

像Nd5e3这种歧义,正则只能帮我们提取候选,最终的正确性还要结合棋局规则判断:

  • 如果是单步:校验d5到e3是不是马的合法走法(马走日,坐标差符合(±1,±2)或(±2,±1))
  • 如果是走法对:校验白方Nd5和黑方e3是不是各自的合法走法

这部分属于业务逻辑,没法靠正则搞定,但正则已经帮我们把所有可能的候选提取出来了,剩下的校验就简单多了。

总结

这套思路的核心是先拆回合,再拆走法对,把复杂的全局匹配拆成两个简单的步骤,既优雅又容易维护,完全适配iOS/Swift的NSRegularExpression环境。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 21:37:50