如何用Chess.js或工具验证所有国际象棋代数记法有效性?
验证任意国际象棋代数记法的有效性
需求说明
我需要验证一个字符串是否属于合法的国际象棋代数记法,不需要考虑这个走法在当前棋局中是否真的能走(比如chess.js的moves()方法只能返回当前局面下的合法走法,满足不了我的需求)。希望能找到现成的字典/工具包,或者自己实现验证逻辑。
举个例子,chess.js初始局面的合法走法是:
const chess = new Chess() chess.moves() // -> ['a3', 'a4', 'b3', 'b4', 'c3', 'c4', 'd3', 'd4', 'e3', 'e4', // 'f3', 'f4', 'g3', 'g4', 'h3', 'h4', 'Na3', 'Nc3', 'Nf3', 'Nh3']
而我需要覆盖的所有合法代数记法包括但不限于:['a1','a2','a3',...,'Ba1','Ba2',...,'a8=Q',...,'a8=N+']这类形式。
解决方案
方法一:正则表达式匹配
国际象棋代数记法(SAN)有明确的语法规则,可以用正则表达式直接匹配验证。以下是一个覆盖大部分常见情况的正则:
const sanRegex = /^([KQRBN]?[a-h]?[1-8]?x?[a-h][1-8](?:=[KQRBN])?[+#]?|O-O(?:-O)?)$/;
正则规则拆解:
[KQRBN]?:可选的棋子标识(K王、Q后、R车、B象、N马,兵无需标识)[a-h]?[1-8]?:可选的消除歧义的位置(比如两个马能走到同一格子时,会加原位置的列/行,如Nbd2)x?:可选的吃子符号(x表示吃子)[a-h][1-8]:必填的目标格子(比如a3、d8)(?:=[KQRBN])?:可选的升变标识(兵走到底线升变,如a8=Q)[+#]?:可选的将军/将死标识(+将军,#将死)|O-O(?:-O)?:王车易位的特殊记法(短易位O-O,长易位O-O-O)
使用示例:
function isValidSAN(san) { const sanRegex = /^([KQRBN]?[a-h]?[1-8]?x?[a-h][1-8](?:=[KQRBN])?[+#]?|O-O(?:-O)?)$/; return sanRegex.test(san); } // 测试用例 console.log(isValidSAN('a3')); // true console.log(isValidSAN('Na3')); // true console.log(isValidSAN('a8=Q+')); // true console.log(isValidSAN('Rxe4#')); // true console.log(isValidSAN('O-O')); // true console.log(isValidSAN('abc')); // false
方法二:使用专门的棋类工具库
如果不想自己维护正则,可以用支持独立解析代数记法的工具库:
- chessops:该库提供
parseSan函数,可直接解析代数记法字符串,无需依赖当前棋局状态。解析失败会抛出错误,以此判断有效性。
使用示例:import { parseSan } from 'chessops'; function isValidSAN(san) { try { parseSan(san); return true; } catch (e) { return false; } } - chess.js:虽然它的
moves()只返回当前局面合法走法,但可以通过创建任意棋盘,尝试用move()方法执行目标记法并捕获错误——不过这个方法有局限性,部分合法记法在特定棋盘下无法执行,不如chessops直接。
内容的提问来源于stack exchange,提问作者INTODAN
相关产品推荐
相关产品推荐

