国际象棋移动(SAN)的RegEx帮助

时间:2016-10-12 20:38:18

标签: java regex

我正在编写一个应该能够读取和解析国际象棋动作的程序(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)......还有什么我可以标记正则表达式的各个部分,这样当它被检测到时,我得到了所有的信息?我试图阅读有关它的文档,但没有弄明白。

有什么建议吗?

4 个答案:

答案 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

以此类推。

相关问题