【问题标题】:Regex challenge, Custom Chess Notation正则表达式挑战,自定义国际象棋符号
【发布时间】:2014-05-13 18:05:42
【问题描述】:
Place a piece on the board (ex: Qld1 – place the white queen on D1, Kde8 – place the black king on E8).  Piece abbreviations are:
K = king
Q = queen
B = bishop
N = knight
R = rook
P = pawn
and l = light, d = dark.

Move a single piece on the board (ex: d8 h4 – moves the piece at D8 to the square at H4, c4 d6* - moves the piece at C4 to D6 and captures the piece at D6).
Move two pieces in a single turn (ex: e1 g1 h1 f1 – moves the king from E1 to G1 and moves the rook from H1 to F1.  This is called a “king-side castle”).

我需要帮助编写一个正则表达式来获取列出的所有选项。我已经走到这一步了:

([KQNBR]?([a-h]?[1-8]?x)?[a-h]([2-7]|[18](=[KQNBR])?)|0-0(-0)?)(\(ep\)|\+{1,2})?

([BKNPQR]?)([a-h]?)([0-9]?)([x=]?)([BKNPQR\*]|[a-h][1-8])([+#]?)

在决定棋盘将采用非常不同的自定义符号来处理移动之前。

问题是我需要帮助来创建将验证这些国际象棋动作的正则表达式。

一个例子是,这个程序不会实时操纵棋盘。但是,文件将从流中逐行读取,您的国际象棋游戏的控制台应用程序应读取每一行并为每个移动生成以下结果。

文件的前几行应该读取每个棋子 Qld1 的位置,它将白皇后放在 D1 上,kde8 将黑王放在 E8 上。

之后文件会读取每一个动作,d8 h4会将d8位置的棋子移动到h4。

单个正则表达式将验证要读取的文本文件是否是基于其表达式的有效移动。如果无效,请跳过移动并继续。

【问题讨论】:

标签: regex expression notation


【解决方案1】:

作为创建复杂正则表达式的一般策略,您可以为每个单独的组件创建不同的正则表达式。

例如首先创建一个正则表达式匹配放置([KQNBR][ld][a-h][1-8])。这易于阅读和创建。

然后为正常移动创建一个正则表达式([a-h][1-8]\s[a-h][1-8]),然后为易位移动创建一个正则表达式(留给读者作为练习)。您可以使用([KQNBR][ld][a-h][1-8])|([a-h][1-8]\s[a-h][1-8]\*?)|etc 组合这些。

您甚至可以重用正则表达式的一部分,例如用您选择的语言调用[a-h][1-8] field 并重复使用它。移动将类似于field + '\s' + field + '\*?'

虽然这可能不是最短的正则表达式(或最有效的),但它会更容易创建并且更具可读性。

【讨论】:

  • 非常有趣,如何验证一个片段捕获? c4 d6*
  • 我已经更新了 move 的正则表达式以包含可选的星号。
  • puu.sh/8MrHN.png qld6 等用于放置 Queen Light D6(位置)或 qda4(Queen Dark A4)的展示位置呢
  • 你的意思是允许小写字母?要么使用 '[KQNBRkqnbr]' 要么使用一些不区分大小写的标志。
  • 哦,是的,我修好了。谢谢你。它也有助于其他符号。
【解决方案2】:

我创建了以下正则表达式,用于将复制的 chess24.com 游戏转换为 PGN-compatible 游戏:

\s*(\d{1,3})\.?\s*((?:(?:O-O(?:-O)?)|(?:[KQNBR][1-8a-h]?x?[a-h]x?[1-8])|(?:[a-h]x?[a-h]?[1-8]\=?[QRNB]?))\+?)(?:\s*\d+\.?\d+?m?s)?\.?\s*((?:(?:O-O(?:-O)?)|(?:[KQNBR][1-8a-h]?x?[a-h]x?[1-8])|(?:[a-h]x?[a-h]?[1-8]\=?[QRNB]?))\+?)?(?:\s*\d+\.?\d+?m?s)?

替换字段为

\1. \2 \3\n 

或者

$1. $2 $3\n

取决于您的正则表达式环境或正则表达式引擎。

Python 中的详细正则表达式:

chess_pattern = re.compile(r"""
\s*                                     # Whitespace
(\d{1,3})                               # Capture group 1: Move number between 1 and 999 will precede white side's move.
\.?                                     # Literal period, in case move numbers followed by a period. The replace pattern will restore period, so it is not captured. 
\s*                                     # Whitespace
(                                       # Capture group 2: This will collect the white side's move
(?:                                     # Start non-capturing group A: Use vertical bar | between non-capturing groups to check for castling, piece moves/captures, pawn moves/captures/promotion
(?:O-O(?:-O)?)                          # Non-capturing subgroup A1: For castling kingside or queenside. Change the O to 0 to work for sites that 0-0 for castling notation
|(?:[KQNBR][1-8a-h]?x?[a-h]x?[1-8])     # Non-capturing subgroup A2: For piece (non-pawn) moves and piece captures
|(?:[a-h]x?[a-h]?[1-8]\=?[QRNB]?)       # Non-capturing subgroup A3: Pawn moves, captures, and promotions
)                                       # End non-capturing group A
\+?                                     # Allow plus symbol for checks (attacks on king)
)                                       # End capturing group 2: White side's move
(?:\s*\d+\.?\d+?m?s)?                   # Non-capturing group B: Skip over move-times; it is possible to retain move times if you make this a capturing group
\.?                                     # Allow period in case a time ends in a decimal point
\s*                                     # Whitespace
(                                       # Capture group 3: This will collect the black side's move
(?:                                     # Start non-capturing group C: Use vertical bar | between non-capturing groups to check for castling, piece moves/captures, pawn moves/captures/promotion
(?:O-O(?:-O)?)                          # Non-capturing subgroup C1: For castling kingside or queenside. Change the O to 0 to work for sites that 0-0 for castling notation
|(?:[KQNBR][1-8a-h]?x?[a-h]x?[1-8])     # Non-capturing subgroup C2: For piece (non-pawn) moves and piece captures
|(?:[a-h]x?[a-h]?[1-8]\=?[QRNB]?)       # Non-capturing subgroup C3: Pawn moves, captures, and promotions
)                                       # End non-capturing group C
\+?                                     # Allow plus symbol for checks (attacks on king)
)?                                      # End capturing group 3: Black side's move. Question mark allows final move to be white side's move without any subsequent black moves
(?:\s*\d+\.?\d+?m?s)?                   # Non-capturing group D: Skip over move-times; it is possible to retain move times if you make this a capturing group
""",re.VERBOSE)
# Paste the entire chess game inside the raw string below where there is currently ...
chess_game = """ 
...
"""
print( pattern.sub(r'\1. \2 \3 '+'\n',chess_game) ) # Will output PGN to console
# The following writes the PGN to a file `game.pgn` in the working directory
output_PGN = open('game.pgn','w+')
output_PGN.write(pattern.sub(r'\1. \2 \3 '+'\n',chess_game))
output_PGN.close()

请参阅此处以获取此操作的示例:regexr.com/58ngb

我还在这里将上述内容实现为Clipboard Fusion (C#) 宏:https://www.clipboardfusion.com/Macros/View/?ID=d220984d-faa4-4ba2-ab86-f16dceb42036

【讨论】:

    【解决方案3】:

    你可以试试这个正则表达式:

    ([BKNPQR][ld][a-h][1-8])|((?:(?:[a-h][1-8]\s*){2})+)
    

    第一部分是set-command:([BKNPQR][ld][a-h][1-8])

    第二部分是移动命令。由于它可以同时包含 1 个或多个动作,因此我需要使用 + 运算符。

    这个语句代表一个动作:(?:[a-h][1-8]\s*){2}

    ?: 只是一些小的性能改进。这意味着,()-brackets 不会被放入匹配中。

    我在这里测试过,它似乎工作:http://regex101.com/

    注意:正则表达式有很多种,它们都很相似,但并不完全相同。我的正则表达式适用于 JavaScript,但由于它只使用基本的正则表达式规则,它也应该适用于任何其他语言。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-15
      • 1970-01-01
      • 1970-01-01
      • 2019-05-30
      • 2022-07-22
      相关资源
      最近更新 更多