我正在编写一个应该能够读取和解析国际象棋动作的程序(SAN)。
以下是可能接受的行动的示例:
e4
Nf3
Nbd2
Nb1c3
R1a3
d8=Q
exd5
Nbxd2
...
我首先编写了NFA,然后将其转换为语法,然后将其转换为正则表达式。
根据我的惯例,这就是它的外观
pln + plxln + plnxln + plnln + plln + pxln + lxln=(B+R+Q+N) + lxln + lnxln=(B+R+Q+N) + lnxln + lnln=(B+R+Q+N) + lnln + ln=(B+R+Q+N) + ln + pnxln + pnln
其中:
p
是一组{B,R,Q,N,K}
的字符(或者将其视为(B+R+Q+N+K)
= [BRQNK]
l
是[a-h]
区间(区分大小写)
n
是[1-8]
区间
+
表示联盟操作...如果我说得对,(B+R+Q+N)
是正则表达式编程语言中的[BRQN]
。
=
只是一个正常的角色...在国际象棋中它用于促销(例如e8 = Q)
x
也是一个普通的角色......当你在那个位置移动你的棋子时,就会使用对手的那个。
(
/ )
:与数学一样
我尝试将第一部分pln
解析为:[BRQN][a-h][1-8]
在一个在线java正则表达式测试器中,并为Nf3
之类的移动工作。我不太清楚如何为复合表达式做联合事情(比如pln+plxln
)......还有什么我可以标记正则表达式的各个部分,这样当它被检测到时,我得到了所有的信息?我试图阅读有关它的文档,但没有弄明白。
有什么建议吗?
答案 0 :(得分:2)
您的注释中的+
在正则表达式中为|
。所以你可以使用正则表达式
[BRQNK][a-h][1-8]|[BRQNK][a-h]x[a-h][1-8]|[BRQNK][a-h][1-8]x[a-h][1-8]|[BRQNK][a-h][1-8][a-h][1-8]|[BRQNK][a-h][a-h][1-8]|[BRQNK]x[a-h][1-8]|[a-h]x[a-h][1-8]=(B+R+Q+N)|[a-h]x[a-h][1-8]|[a-h][1-8]x[a-h][1-8]=(B+R+Q+N)|[a-h][1-8]x[a-h][1-8]|[a-h][1-8][a-h][1-8]=(B+R+Q+N)|[a-h][1-8][a-h][1-8]|[a-h][1-8]=(B+R+Q+N)|[a-h][1-8]|[BRQNK][1-8]x[a-h][1-8]|[BRQNK][1-8][a-h][1-8]
显然,这有点难看。我可以想出两种可能的方法来使它变得更好:
COMMENTS
标志,您可以添加空格。 [BRQNK][a-h]x[a-h][1-8]|[BRQNK][a-h][1-8]x[a-h][1-8]
可以重写为[BRQNK][a-h][1-8]?x[a-h][1-8]
。我也知道java中没有的另一项改进。 (也许不是很多语言,但你可以在Perl中完成。)子表达式(?1)
(同样(?2)
等)有点像\1
,除了它不是精确匹配与第一个捕获组匹配的字符串,它匹配可能与该捕获组匹配的任何字符串。换句话说,它相当于再次编写捕获组。因此,您可以(在Perl中)将第一个[BRQNK]
替换为([BRQNK])
,然后将所有后续匹配项替换为(?1)
。
答案 1 :(得分:1)
/^([NBRQK])?([a-h])?([1-8])?(x)?([a-h][1-8])(=[NBRQK])?(\+|#)?$|^O-O(-O)?$/
这是针对2599个案例的单元测试。请参阅下面的单元测试
describe('Importer/Game', function() {
let Importer, Game;
beforeEach(function() {
Importer = require(`${moduleDir}/import`).Importer;
Game = require(`${moduleDir}/import`).Game;
});
describe('moveRegex', function() {
describe('non-castling', function() {
// ([NBRQK])? ([a-h])? ([1-8])? (x)? ([a-h][1-8]) (=[NBRQK])? (+|#)?/
// unitType? startFile? startRank? capture? end promotion? checkState?
for(let unitType of ['', 'N', 'B', 'R', 'Q', 'K']) {
for(let startFile of ['', 'b']) {
for(let startRank of ['', '3']) {
for(let capture of ['', 'x']) {
for(let promotion of ['', '=Q']) {
for(let checkState of ['', '+', '#']) {
//TODO: castling
const dest = 'e4';
const san = unitType + startFile + startRank + capture + dest + promotion + checkState;
testPositive(san);
//TODO: negative substitutions here.
testNagative('Y' + startFile + startRank + capture + dest + promotion + checkState);
testNagative(unitType + 'i' + startRank + capture + dest + promotion + checkState);
testNagative(unitType + startFile + '9' + capture + dest + promotion + checkState);
testNagative(unitType + startFile + startRank + 'X' + dest + promotion + checkState);
testNagative(unitType + startFile + startRank + capture + 'i9' + promotion + checkState);
// testNagative(unitType + startFile + startRank + capture + '' + promotion + checkState);
testNagative(unitType + startFile + startRank + capture + dest + '=' + checkState);
testNagative(unitType + startFile + startRank + capture + dest + 'Q' + checkState);
testNagative(unitType + startFile + startRank + capture + dest + promotion + '++');
}
}
}
}
}
}
});
describe('castling', function() {
testPositive('O-O');
testPositive('O-O-O');
testNagative('OOO');
testNagative('OO');
testNagative('O-O-');
testNagative('O-O-O-O');
testNagative('O');
});
function testPositive(san) {
it(`should handle this san: ${san}`, function(done) {
const matches = san.match(Importer.moveRegex);
assert(matches);
done();
});
}
function testNagative(san) {
it(`should not match this: ${san}`, function(done) {
const matches = san.match(Importer.moveRegex);
assert(!matches);
done();
});
}
});
});
答案 2 :(得分:0)
我在网络门户网站上已经使用了一段时间。
[BRQNK][a-h][1-8]| [a-h][1-8]|[BRQNK][a-h][a-h][1-8]|O-O|0-0-0|[BRQNK]x[a-h][1-8]|[a-h]x[a-h][1-8]|1\/2-1\/2|1\/-O|O-\/1
答案 3 :(得分:0)
Re: /^([NBRQK])?([a-h])?([1-8])?(x)?([a-h][1-8])(=[NBRQK])?(\+|#)?$|^O-O(-O)?$/
既包含不足又包含过多。
它不包括可能的合法举动O-O+, O-O-O+, O-O#, and O-O-O#.
它包含许多永远不会合法的字符串:e8=K, Kaa4, Nf5=B, Qa1xb7
以此类推。