Schachzug per regexp validieren und u.U. auch zerlegen

25/03/2014 - 00:59 von Christian H. Kuhn | Report spam
Hallo Gemeinde,

Vor einiger Zeit habe ich hier nach einem PGN-Parser gefragt. Die Antworten
waren alle sehr interessant, vielen Dank dafür! Eine vollstàndige Lösung war
aber leider nicht dabei. Inzwischen habe ich mal ein paar Stunden Zeit
gefunden, den umfangreichsten Teil selbst geschrieben und dabei eine Menge
über Endliche Automaten gelernt :-)

Jetzt fehlt der Kernpunkt: Ich möchte alle möglichen Züge (außer der
Rochade, die geht extra) erkennen und wenn möglich auch zerlegen. Die regexp
habe ich bis auf ein paar Feinheiten im Prinzip:

([PNBRQK]?)([a-h]?)(x?)([a-h]{1})([1-8]{1})([NBRQ]?)([\+#]?)(((e.p.)|(ep.)|
(ep))?)

Die fehlenden Feinheiten sind:
– die beiden Gruppen mit Großbuchstaben schließen sich gegenseitig aus;
– das x darf nur vorkommen, wenn mindestens eine der beiden Gruppen davor
vorhanden ist;
– e.p. ist nur erlaubt, wenn die Ziffer eine 3 oder 6 ist.

Wenn mir da einer eine einfache, verstehbare Lösung nennen kann, wàre das
nicht schlecht. Für den normalen Einsatz reicht es so auch; die Probleme
kann man auch beim Einfügen des Zuges in eine Partie mit Repràsentation des
Brettes abfangen, das muss nicht schon beim Parsen passieren.

Den gesamten Zug kann ich mit Pattern und Matcher, find() und group()
extrahieren. Das ist noch nicht gecodet, aber theoretisch gelöst.

Wichtiger wàre die Zerlegung. Im obersten Level sind 8 Gruppen, und die
möchte ich alle haben. Wichtig ist dabei, dass beim Input "d4" der Output

"","","",d,4,"","",""

und nicht

"",d,"","",4,"","",""

ist. Noch besser wàre, die Gruppen 4 und 5 zu einer zusammenzufassen.

Ja, das geht mit nett verschachtelten if-Ketten. Mit Lesbarkeit und Eleganz
;-) hat das weniger zu tun. Wenn es anders nicht geht, mach ich es so. Wenn
mir jemand einen Tipp geben kann, wie das mit regexp geht, wàre das viel
besser.

mfg
QNo
 

Lesen sie die antworten

#1 ram
25/03/2014 - 03:58 | Warnen spam
"Christian H. Kuhn" writes:
([PNBRQK]?)([a-h]?)(x?)([a-h]{1})([1-8]{1})([NBRQ]?)([\+#]?)



class TokenSource
{ final java.lang.String string;
public TokenSource( final java.lang.String string )
{ this.string = string; };
int p = 0;
int get(){ return p >= this.string.length() ? 0 : this.string.codePointAt( p ); }
void next()
{ if( p < this.string.length() )p += java.lang.Character.charCount( get() ); }}

public class Main
{
public static int movingPieceLetter( final TokenSource src )
{ final int letter = src.get(); int result = -1;
switch( letter )
{ case( int )'P': case( int )'N': case( int )'B':
case( int )'R': case( int )'Q': case( int )'K':
result = letter; src.next(); }
return result; }

public static int fileLetter( final TokenSource src )
{ final int letter = src.get(); int result = -1;
if( letter >= 'a' && letter <= 'h' ){ result = letter; src.next(); }
return result; }

public static int fileNumber( final TokenSource src )
{ final int letter = src.get(); int result = -1;
if( letter >= '1' && letter <= '8' ){ result = letter; src.next(); }
return result; }

public static boolean isCapture( final TokenSource src )
{ final int letter = src.get(); boolean result = false;
if( letter == 'x' ){ result = true; src.next(); }
return result; }

public static int pawnPromotion( final TokenSource src )
{ final int equals = src.get(); int result = -1;
if( equals == '=' )
{ src.next();
final int letter = src.get();
switch( letter )
{ case( int )'N': case( int )'B': case( int )'R': case( int )'Q':
result = letter; src.next(); }}
return result; }

public static int check( final TokenSource src )
{ final int letter = src.get(); int result = -1;
if( letter == '+' || letter == '#' ){ result = letter; src.next(); }
return result; }

public static void print( final java.lang.String label, final int letter )
{ if( letter != -1 )
{ java.lang.System.out.print( label + " = \"" );
java.lang.System.out.print( letter < 65535 ?( char )letter : '?' );
java.lang.System.out.println( "\"" ); }}

public static void print( final java.lang.String label, final boolean value )
{ java.lang.System.out.print( label + " = " );
java.lang.System.out.print( value ? "yes" : "no" );
java.lang.System.out.println(); }

public static void src( final java.lang.String string )
{ java.lang.System.out.println();
java.lang.System.out.println( string );
final TokenSource src = new TokenSource( string );
final int movingPieceLetter = movingPieceLetter( src );
final int pendingFileLetter = fileLetter( src );
final boolean capture = isCapture( src );
final int destinationLetter = capture ? fileLetter( src ) : pendingFileLetter;
final int destinationNumber = fileNumber( src );
final int pawnPromotion = pawnPromotion( src );
final int check = check( src );
print( " moving piece:", movingPieceLetter );
if( capture )print( " originating pawn:", pendingFileLetter );
print( " capture:", capture );
print( "destinationLetter:", destinationLetter );
print( "destinationNumber:", destinationNumber );
print( " pawnPromotion:", pawnPromotion );
print( " check:", check ); }

public static void main( final java.lang.String[] args )
{ final java.lang.String[] move = { "d4", "Nf3", "Qaxb7#", "fxg1=Q+" };
for( final java.lang.String m : move )src( m ); }}

d4
capture: = no
destinationLetter: = "d"
destinationNumber: = "4"

Nf3
moving piece: = "N"
capture: = no
destinationLetter: = "f"
destinationNumber: = "3"

Qaxb7#
moving piece: = "Q"
originating pawn: = "a"
capture: = yes
destinationLetter: = "b"
destinationNumber: = "7"
check: = "#"

fxg1=Q+
originating pawn: = "f"
capture: = yes
destinationLetter: = "g"
destinationNumber: = "1"
pawnPromotion: = "Q"
check: = "+"

Ähnliche fragen