TicTacToe 在 java 中使用正则表达式



使用正则表达式创建一个 tictactoe 接收九个"X"、"O"和/或"-"字符的字符串的函数,表示井字棋板的状态,例如字符串:"X-OXXXO-O"这代表:

X-O
XXX
O-O

更多示例:


"XOOOXXXXO" - False - no one got three in a row here.
"OXO-XOX-O" - True - player O won by getting three in a row vertically in the third column.

这是我编写代码的尝试:

public static boolean regexTicTacToeWinChecker(String b) {
return b.matches("(((^(...)*000(...)*$)|(.*0..0..0.*)|(0(...0{2}))|(.(.0){3}..))) | (((^(...)*XXX(...)*$)|(.*X..X..X.*)|(X(...X){2})|(.(.X){3}..)))");
}

使用正则表达式比编写大量涵盖所有情况的 if 更有用。 所以请回答 rejex,帮助将不胜感激。 谢谢 以下是一些可用于检查的测试:

import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.runners.JUnit4;
public class ExampleTestCases {
@Test
public void SomeBoardsWithWinnersTests () {
String[] winners = new String[]{"XXX-O-O-O", "X--OOOX-X", "O--OO-XXX", "O-XOX-O-X", "OXOOXOXX-", "X-O-OOXXO", "XO--X-OOX", "X-OXOOOXX"};
for (String winner : winners) {
System.out.println("Testing with board " + winner);
assertEquals(true, RegexTicTacToeWinChecker.regexTicTacToeWinChecker(winner));
}
}
@Test
public void SomeBoardsWithoutWinnersTests () {
String[] notWinners = new String[]{"XO-------", "XX-XOO---", "-XX-OO-O-", "OXO--XXO-", "OOXXXO---", "OXXX-XOO-", "OOXXX----", "XXOOXXOO-", "OXOXOX---"};
for (String notWinner : notWinners) {
System.out.println("Testing with board " + notWinner);
assertEquals(false, RegexTicTacToeWinChecker.regexTicTacToeWinChecker(notWinner));
}
}
}

您可以将其分解为个别情况:

水平匹配:

(?:...){0,2}([OX])11

垂直匹配:

.{0,2}([OX])..2..2

对角线匹配(两个方向):

([OX])...3...3
..([OX]).4.4

现在,您只需将它们全部or在一起,并确保正则表达式在板字符串的开头匹配:

^(?:(?:...){0,2}([OX])11|.{0,2}([OX])..2..2|([OX])...3...3|..([OX]).4.4)

编辑:这是一个测试正则表达式的小型Java程序:

import java.util.regex.*;
public class TicTacToe {
public static void main(String[] args) {
Pattern r = Pattern.compile("^(?:(?:...){0,2}([OX])\1\1|.{0,2}([OX])..\2..\2|([OX])...\3...\3|..([OX]).\4.\4)");
String board = "XXX-O-O-O";

Matcher m = r.matcher(board);
System.out.println(m.lookingAt() ? "match" : "no match");
}
}

如果您希望能够在几个月内维护您的正则表达式,我宁愿选择更具可读性的东西,而不是老实说过于聪明,例如;

Vertical match:   X..X..X..|.X..X..X.|..X..X..X
Horizontal match: XXX......|...XXX...|......XXX
Diagonal match:   X...X...X|..X.X.X..

一起:

^(?:X..X..X..|.X..X..X.|..X..X..X|XXX......|...XXX...|......XXX|X...X...X|..X.X.X..)$

这使得仅通过查看正则表达式即可几乎看到获胜模式。

O做同样的事情,你应该很高兴去:)

我宁愿让你的正则表达式尽可能简单!这意味着您需要停止将所有内容压缩到一根字符串。

想象一下以下内容:

XOX
OOX
XXO

为什么不从中创建几个字符串:

  1. 水平线:XOX
  2. 水平线:OOX
  3. 水平线:XXO

  1. 垂直线:XOX
  2. 垂直线:OOX
  3. 垂直线:XXO

  1. 顶部 LEF 对角线:XOO
  2. 左下角对角线:XOX

并针对以下各项运行其中每个值:

"^X{3}$" = player 1 won
"^O{3}$" = player 2 won

在代码中:

Pattern player1Pattern = Pattern.compile("^X{3}$");
Pattern player2Pattern = Pattern.compile("^O{3}$");
for(String s: tictactoe) {
if(player1Pattern.matcher(s).matches()){
//Player 1 wins
}else if(player2Pattern.matcher(s).matches()){
//Player 2 wins
}else{
//nobody wins
}
}

你可以试试这个:

查看正则表达式演示

我只是将输入作为模式输入:

X-O
XXX
O-O
Pattern pattern = Pattern.compile("([XO])(?:(?:\1\1)|(?:(?:[\sXO-]{2}\1){2})|(?:[\sXO-]{3}\1){2}|(?:[\sXO-]{4}\1){2})", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher("X-On" +
"XXXn" +
"O-O");
boolean matchFound = matcher.find();
if(matchFound) {
System.out.println("Match found and "+ matcher.group(1) + " win!");
} else {
System.out.println("Match not found!");
}

输出:

Match found and X win!

最新更新