2012-05-11 25 views
1

为了学术目的,我们的基本团队(我和一个朋友)正在用java编写基于瓦片的游戏。为了使用这些图块,我们已经给出了一个配置文件,其中包含每个图层中所有图块的字符串表示形式,每行一次。下面是一些例子:单独的正则表达式匹配,但它们的联合不匹配

N=N S=C O=C E=N NS=0 NE=0 NO=0 OE=0 SE=0 SO=1 
N=S S=S O=S E=S NS=0 NE=0 NO=0 OE=0 SE=0 SO=0 

在上面的陈述,N,S,O和E映射到东南西北北,南,东,西,而前四个作业权成员映射到道路( S),城市(C)和现场(N)。以下六组表示两点之间是否存在关联。例如,SO = 1意味着南部和西部相连。

我们的第一个想法是使用标准Java库提供的Pattern类来解析这些具有正则表达式的行。我的队友编写了一个代码,为整个字符串生成一个模式,组装更小的模式,指示某些枚举的可能值(以前的位置包含基点和AssetType以包含像道路或城市这样的结构)。我不会粘贴代码,因为它非常耗费空间并且不够优雅。但是,我可以授予您这是正确的。在开始之前,我想指出的是,瓷砖字符串实际上是由两个主要部分组成:边界(即前4个分配)和链接(后6个)的规定。因此,我们有两个解析器。第一个能够解析字符串,如“N = N S = C O = C E = N”,第二个“NS = 0 NE = 0 NO = 0 OE = 0 SE = 0 SO = 1”。他们的模式是正确的。我们已经对它们进行了全面测试,所有测试都顺利通过

现在来蹭。由于拼块字符串总是由第一部分和第二部分组成,因此我们为整个字符串创建了模式,只是为第一部分和第二部分添加了模式,用\ s +分隔它们并围绕它们中的每一个与parantheses。由此产生的表达式如下:

(N\s*\=\s*(N|S|C)(,(R|B|V|G|N))?\s+S\s*\=\s*(N|S|C)(,(R|B|V|G|N))?\s+O\s*\=\s*(N|S|C)(,(R|B|V|G|N))?\s+E\s*\=\s*(N|S|C)(,(R|B|V|G|N))?)\s+(NS\s*\=\s*(0|1)\s+NE\s*\=\s*(0|1)\s+NO\s*\=\s*(0|1)\s+OE\s*\=\s*(0|1)\s+SE\s*\=\s*(0|1)\s+SO\s*\=\s*(0|1)) 

这看起来很糟糕,我知道,但它是编译时结果。尽管如此,我们对某些字符串进行了测试,就像我之前发布的那些字符串,但发现它们不匹配,尽管单个模式匹配。 我们试图在线模拟器上运行它,如this,它完美匹配。我们不知道如何使它匹配。有任何想法吗?

一些一段代码:

public Tile from(String tileString) { 
    Matcher matcher = pattern.matcher(tileString); 

    return new InnerTile(
      tileBorderBuilder.from(matcher.group(1)), 
      tileLinkageBuilder.from(matcher.group(14))); 
} 

tileBorderBuilder.from解析的第一部分,并返回一个TileBorder对象。 tileLinkageBuilder.from做同样的事情并返回一个TileLinkage对象。它会抛出一个异常:“找不到匹配”。

P.S .:我们正在使用Java SE 1.6或Open-JDK6(它们都会失败)。

回答

0

喜欢这个调试问题,开始用更简单的正则表达式,并建立从那里,即尝试匹配

N=N 
N=N S=C 
... 
N=N S=C O=C E=N NS=0 NE=0 NO=0 OE=0 SE=0 SO=1 

(相应缩短正则表达式)。这将帮助您确定发生问题的正则表达式的位置。

这就是说,我建议这个正则表达式来解析配置:

\s*([^\s=]+)\s*=\s*(\S) 

斯普利特输入线,然后反复应用此每行读取每个“单词”。

这是Java方面的更多努力,但它保持了正则表达式的检查并使您的代码易于阅读,理解和扩展...因为几天后,您将添加另一个tile或新的选项 - 一个月后,正则表达式将控制你的生活。

+0

我无法逐步匹配正则表达式,因为它会打破两个组之间的分离,但我会在内部尝试。我试过了“((N | S | E | O)\\ s * \\ = \\ s *(S | C | N)(,(R | G | V | N | B))?\\ s *){4} \\ s +((N | S | E | O){2} \\ s * \\ = \\ s *(0 | 1)\\ s *){6}“, ,它的工作原理。然而,我的队友是非常固执的,他不会接受它,因为他想要为每个标签保持完全相同的显示顺序。也就是说,你的正则表达式虽然简单,但会匹配每个单词,但我们需要这些特定的字符。 – Totem

+0

感谢您的回答。我解决了将第一个匹配到find(),然后第二个匹配find(int)将第一个子串结尾的索引传递给它。我还测试了许多其他正则表达式,但Java中的正则表达式支持非常可怕。 – Totem

+0

http://programmers.stackexchange.com/questions/10998/what-does-the-jamie-zawinskis-quotation-about-regular-expressions-mean –