1

学術的な目的のために、私たちの重要なチーム(私と友人)は、Javaでタイルベースのゲームをプログラミングしています。これらのタイルで遊ぶために、デッキ内のすべてのタイルの文字列表現を1行に1回含む構成ファイルが提供されています。ここではいくつかの例を示します。

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は北、南、東、西の主要ポイントにマップされ、最初の4つの割り当ての右側のメンバーは道路(S)、都市(C)、およびフィールド(N)にマップされます。 。次の6つのグループは、2つのポイント間にリンクが存在するかどうかを示します。たとえば、SO = 1は、南と西がリンクされていることを意味します。

私たちの最初のアイデアは、標準のJavaライブラリによって提供されるPatternクラスを使用して、正規表現でこれらの行を解析することでした。私のチームメイトは、文字列全体のパターンを生成するコードを作成し、いくつかの列挙の可能な値を示す小さなパターンを組み立てました(以前は、基点を含むPositionと、道路や都市などの構造を含むAssetType)。かなりスペースを消費し、あまりエレガントではないため、生成用のコードは貼り付けません。しかし、私はそれが正しいことをあなたに認めることができます。

先に進む前に、タイル文字列が実際に構成されている2つの主要な部分、つまり境界線の指定(つまり、最初の4つの割り当て)とリンクの指定(最後の6つ)であることを指摘しておきます。したがって、2つのパーサーがあります。1つ目は「N=NS = CO = CE = N」のような文字列を解析でき、2つ目は「NS = 0 NE = 0 NO = 0 OE = 0 SE = 0SO=1」のような文字列を解析できます。それらのパターンは正しいです。私たちはそれらを徹底的にテストし、すべてのテストはスムーズに合格しました。

そして今、摩擦が来ます。タイル文字列は常に最初の部分と2番目の部分で構成されているため、最初の部分と2番目の部分のパターンを追加し、\ s +で区切り、それぞれを囲むだけで、文字列全体のパターンを作成しました。パターン付き。結果の式は次のとおりです。

(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))

ひどいように見えますが、コンパイル時の結果です。それでも、上記で投稿したようないくつかの文字列に対してテストしたところ、単一のパターンは一致していても、一致しないことがわかりました。このようにオンラインシミュレーターで実行しようとしましたが、完璧に一致します。一致させる方法がわかりません。何か案は?

コードの一部:

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オブジェクトを返します。「一致するものが見つかりません」という例外がスローされます。

PS:Java SE 1.6またはOpen-JDK6を使用しています(両方で失敗します)。

4

1 に答える 1

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側ではより手間がかかりますが、正規表現を抑制し、コードを読みやすく、理解しやすく、拡張しやすくします...数日以内に、別のタイルまたは新しいオプションを追加する予定です。 1か月後、正規表現があなたの人生を支配するようになります。

于 2012-05-11T15:13:51.667 に答える