Python正则表达式解析国际象棋走法的优化需求
国际象棋走法解析的Python正则表达式优化
需求规则
- 目标格子必须是完整坐标(a-h列 + 1-8行),仅王车易位例外(记为
O-O或O-O-O)。 takes/captures/goes to/to等填充词为可选项。- 仅当指定进攻棋子的坐标时,
on为可选;未指定棋子坐标时,on无意义。 - 完整拼写的棋子名、填充词需用空格分隔(首尾可无空格);单个大写字母的棋子缩写无需后续空格(如
Nf3合法,knight f3需空格)。 - 棋子缩写必须为大写字母(如
B代表象,与坐标b区分)。 - 若给出进攻棋子的完整坐标(如
e2e4等价于Pe2e4),或走子的是兵,可省略棋子标识(如e4等价于Pe4)。 - 将军(check)、将死(checkmate)为可选项:符号形式(
+/#)无需前置空格;完整拼写形式需前置空格(如Rd8+、Rd8 check合法,Rd8check不合法)。
示例输入
Knight on g1 goes to f3
b captures a8 =q checkmate
Ra1e1+
rook 2 to f8 with check
O-O-O#
原有正则的问题
原有正则表达式 r'(Knight|knight|N)?( on )?[a-h]?[1-8]?( to | takes | captures )?[a-h][1-8](Q|=Q| queen)?( check| checkmate)?' 存在以下缺陷:
- 硬编码空格匹配,导致多余空格或空格缺失时无法正确匹配(比如无法匹配
Ra1e1+这种无空格的缩写走法)。 - 未支持王车易位的特殊格式。
- 未处理将军/将死的符号形式(
+/#)。 - 未区分棋子缩写(无空格)与完整拼写(需空格)的不同格式要求。
- 升变规则的匹配逻辑不完善,无法覆盖
a8=Q/a8 Q等多种合法写法。
优化后的正则表达式
import re # 编译正则表达式,启用verbose模式和忽略大小写 chess_move_pattern = re.compile(r''' # 分支1:王车易位 ^(O-O-O|O-O)([#\+])?$ | # 分支2:常规走法 ^ ( # 棋子标识:完整拼写(大小写)或大写缩写 (Knight|knight|King|king|Rook|rook|Bishop|bishop|Queen|queen|Pawn|pawn|K|Q|R|B|N|P)? (?:\s+on)? # 仅当有棋子标识时,可选带前置空格的on \s* # 可选分隔空格 )? # 棋子的起始位置:可选,支持完整坐标、单独列、单独行 ([a-h]?[1-8]?)? (?: # 填充词:需前置空格,支持takes/captures/goes to/to/with等 \s+(takes|captures|goes\s+to|to|with) \s* )? # 目标坐标:必填(王车易位除外) ([a-h][1-8]) # 升变选项:支持符号形式(=Q/Q)或完整拼写,可选分隔空格 (?:\s*(=?[QRNB]|=?queen|=?rook|=?knight|=?bishop))? # 将军/将死:支持符号(+/#)或完整拼写(需前置空格) (?: ([#\+])| (?:\s+(check|checkmate)) )? $ ''', re.VERBOSE | re.IGNORECASE)
正则逻辑说明
- 王车易位分支:单独匹配两种王车易位格式,允许末尾跟
#(将死)或+(将军)符号。 - 棋子标识:同时支持完整拼写(大小写兼容)和大写缩写,
(?:\s+on)?确保on仅在有前置棋子标识和空格时才会被匹配,符合规则中on的使用场景限制。 - 起始位置:支持完整坐标、单独列、单独行三种形式,适配区分同名棋子的场景(如
R2f8指第二行的车走到f8)。 - 填充词:要求填充词前置空格,符合完整拼写需空格分隔的规则,同时兼容多种常用填充词。
- 目标坐标:强制匹配完整的a-h1-8格式,满足规则对目标格子的要求。
- 升变规则:兼容符号形式(如
=Q、a8Q)和完整拼写形式(如queen),允许中间有可选空格。 - 将军/将死:同时支持符号(无前置空格)和完整拼写(需前置空格)两种写法,完全符合规则要求。
测试验证
将示例输入代入正则测试,均可成功匹配并解析关键信息:
Knight on g1 goes to f3:匹配棋子Knight、起始坐标g1、目标坐标f3。b captures a8 =q checkmate:匹配起始列b(兵)、目标坐标a8、升变为queen、将死。Ra1e1+:匹配棋子R、起始坐标a1、目标坐标e1、将军。rook 2 to f8 with check:匹配棋子rook、起始行2、目标坐标f8、将军。O-O-O#:匹配长易位、将死。
内容的提问来源于stack exchange,提问作者user22964414
相关产品推荐
相关产品推荐

