在字符串数组中查找模式 (Java)

Finding a Pattern in an Array of Strings (Java)

大家好吗?我正在尝试创建一个 简单 游戏,其中根据玩家的移动,一些角色会附加到他们的字符串(对于第二个玩家也是如此)。游戏应该检测特定字符是否出现在这些字符串中,而不管它们出现在字符串中的什么位置。需要3个字符的组合才能进步。

因此,举例来说,玩家可能做出的一个成功动作是在其字符串中的某处附加字符“c”、“d”和“e”,例如“abcde”。当游戏在他们的字符串中检测到“cde”时,他们就赢得了一些东西。但是,如果该玩家的字符串是“ifc4_d'e”,尽管包含相同的字符,但游戏不会检测到该胜利。

编辑:下面有三个代码片段,但不要惊慌;后两个只是第一个,但数组 and/or findWinPatterns() 方法略有改变。

这是我的初始代码:

// The following is used for determining local/global wins.
static final String[][] winPatterns = new String[][] {
    // Local board 1
    {"!\"#", "$%&", "\'()", "!$\'", "\"%(", "#&)", "!%)", "\'%#"},
    // Local board 2
    {"*+,", "-./", "0:;", "*-0", "+.:", ",/;", "*.;", "0.,"},
    // Local board 3
    {"<=>", "?@A", "BCD", "<?B", "=@C", ">AD", "<@D", "B@>"},
    // Local board 4
    {"EFG", "HIJ", "KLM", "EHK", "FIL", "GJM", "EIM", "KIG"},
    // Local board 5
    {"NPQ", "RST", "UVW", "NRU", "PSV", "QTW", "NSW", "USQ"},
    // Local board 6
    {"YZ[", "\]^", "`ab", "Y\`", "Z]a", "[^b", "Y]b", "`]["},
    // Local board 7
    {"cde", "fgh", "ijk", "cfi", "dgj", "ehk", "cgk", "ige"},
    // Local board 8
    {"lmn", "opq", "rst", "lor", "mps", "nqt", "lpt", "rpn"},
    // Local board 9
    {"uvw", "xyz", "{}~", "ux{", "vy}", "wz~", "uy~", "{yw"},
    // Global board
    {"123", "456", "789", "147", "258", "369", "159", "357"}
};
    
// WIN DETECTION METHOD

// Flag variables
static boolean flag0, flag1, flag2, flag3, flag4, flag5, flag6, flag7, flag8 = true;

static void findWinPatterns(String score) {
    for (int i = 0; i < winPatterns.length; i++) {
        for (String pattern : winPatterns[i]) {
            if (score.contains(pattern)) {
                System.out.println("3 in a row!" + " i = " + i);
                /*
                switch (i) {
                    case 0:
                    if (flag0) {
                        System.out.println("[Player] has won Local Board 1!");
                        flag0 = false;
                    }
                    break;
                    case 1:
                    if (flag1) {
                        System.out.println("[Player] has won Local Board 2!");
                        flag1 = false;
                    }
                    break;
                    case 2:
                    if (flag2) {
                        System.out.println("[Player] has won Local Board 3!");
                        flag2 = false;
                    }
                    break;
                    case 3:
                    if (flag3) {
                        System.out.println("[Player] has won Local Board 4!");
                        flag3 = false;
                    }
                    break;
                    case 4:
                    if (flag4) {
                        System.out.println("[Player] has won Local Board 5!");
                        flag4 = false;
                    }
                    break;
                    case 5:
                    if (flag5) {
                        System.out.println("[Player] has won Local Board 6!");
                        flag5 = false;
                    }
                    break;
                    case 6:
                    if (flag6) {
                        System.out.println("[Player] has won Local Board 7!");
                        flag6 = false;
                    }
                    break;
                    case 7:
                    if (flag7) {
                        System.out.println("[Player] has won Local Board 8!");
                        flag7 = false;
                    }
                    break;
                    case 8:
                    if (flag8) {
                        System.out.println("[Player] has won Local Board 9!");
                        flag8 = false;
                    }
                    break;
                    case 9:
                    // WINNER DECLARED
                    break;
                }
                */
            }
        }
    }
}
// MAIN METHOD HERE

这个编译通过了,但是因为contains()方法只检测准确的字符串,所以不适合我的游戏。然后我试了这个:

// The following is used for determining local/global wins.
static final String[][] winPatterns = new String[][] {
    // Local board 1
    {"[!\"#]", "[$%&]", "[\'()]", "[!$\']", "[\"%(]", "[#&)]", "[!%)]", "[\'%#]"},
    // Local board 2
    {"[*+,]", "[-./]", "[0:;]", "[*-0]", "[+.:]", "[,/;]", "[*.;]", "[0.,]"},
    // Local board 3
    {"[<=>]", "[?@A]", "[BCD]", "[<?B]", "[=@C]", "[>AD]", "[<@D]", "[B@>]"},
    // Local board 4
    {"[EFG]", "[HIJ]", "[KLM]", "[EHK]", "[FIL]", "[GJM]", "[EIM]", "[KIG]"},
    // Local board 5
    {"[NPQ]", "[RST]", "[UVW]", "[NRU]", "[PSV]", "[QTW]", "[NSW]", "[USQ]"},
    // Local board 6
    {"[YZ\[]", "[\\]^]", "[`ab]", "[Y\`]", "[Z\]a]", "[\[^b]", "[Y\]b]", "[`\]\[]"},
    // Local board 7
    {"[cde]", "[fgh]", "[ijk]", "[cfi]", "[dgj]", "[ehk]", "[cgk]", "[ige]"},
    // Local board 8
    {"[lmn]", "[opq]", "[rst]", "[lor]", "[mps]", "[nqt]", "[lpt]", "[rpn]"},
    // Local board 9
    {"[uvw]", "[xyz]", "[{}~]", "[ux{]", "[vy}]", "[wz~]", "[uy~]", "[{yw]"},
    // Global board
    {"[123]", "[456]", "[789]", "[147]", "[258]", "[369]", "[159]", "[357]"}
};
    
// WIN DETECTION METHOD

// Flag variables
static boolean flag0, flag1, flag2, flag3, flag4, flag5, flag6, flag7, flag8 = true;

static void findWinPatterns(String score) {
    for (int i = 0; i < winPatterns.length; i++) {
        for (String pattern : winPatterns[i]) {
            if (score.matches(pattern)) {
                System.out.println("3 in a row!" + " i = " + i);
// ... all the same stuff as before ...
            }
        }
    }
}
// MAIN METHOD HERE

这也编译了,但是没有用,我想这是因为我的正则表达式很糟糕。我用 this website 来确认这一点,但修复它需要很长时间,而且它似乎也一点也不干净。所以我选择使用 Pattern 和 Matcher 类 来制作一些更易于阅读的代码,并且......好吧:

// The following is used for determining local/global wins; here's where things get UGLY.
static final Pattern[][] winPatterns = new Pattern[][] {
    // Local board 1
    {Pattern.compile("!\"#", Pattern.LITERAL), Pattern.compile("$%&", Pattern.LITERAL), Pattern.compile("'()", Pattern.LITERAL), Pattern.compile("!$'", Pattern.LITERAL), Pattern.compile("\"%(", Pattern.LITERAL), Pattern.compile("#&)", Pattern.LITERAL), Pattern.compile("!%)", Pattern.LITERAL), Pattern.compile("'%#", Pattern.LITERAL)},
    // Local board 2
    {Pattern.compile("*+,", Pattern.LITERAL), Pattern.compile("-./", Pattern.LITERAL), Pattern.compile("0:;", Pattern.LITERAL), Pattern.compile("*-0", Pattern.LITERAL), Pattern.compile("+.:", Pattern.LITERAL), Pattern.compile(",/;", Pattern.LITERAL), Pattern.compile("*.;", Pattern.LITERAL), Pattern.compile("0.,", Pattern.LITERAL)},
    // Local board 3
    {Pattern.compile("<=>", Pattern.LITERAL), Pattern.compile("?@A", Pattern.LITERAL), Pattern.compile("BCD", Pattern.LITERAL), Pattern.compile("<?B", Pattern.LITERAL), Pattern.compile("=@C", Pattern.LITERAL), Pattern.compile(">AD", Pattern.LITERAL), Pattern.compile("<@D", Pattern.LITERAL), Pattern.compile("B@>", Pattern.LITERAL)},
    // Local board 4
    {Pattern.compile("EFG", Pattern.LITERAL), Pattern.compile("HIJ", Pattern.LITERAL), Pattern.compile("KLM", Pattern.LITERAL), Pattern.compile("EHK", Pattern.LITERAL), Pattern.compile("FIL", Pattern.LITERAL), Pattern.compile("GJM", Pattern.LITERAL), Pattern.compile("EIM", Pattern.LITERAL), Pattern.compile("KIG", Pattern.LITERAL)},
    // Local board 5
    {Pattern.compile("NPQ", Pattern.LITERAL), Pattern.compile("RST", Pattern.LITERAL), Pattern.compile("UVW", Pattern.LITERAL), Pattern.compile("NRU", Pattern.LITERAL), Pattern.compile("PSV", Pattern.LITERAL), Pattern.compile("QTW", Pattern.LITERAL), Pattern.compile("NSW", Pattern.LITERAL), Pattern.compile("USQ", Pattern.LITERAL)},
    // Local board 6
    {Pattern.compile("YZ[", Pattern.LITERAL), Pattern.compile("\]^", Pattern.LITERAL), Pattern.compile("`ab", Pattern.LITERAL), Pattern.compile("Y\`", Pattern.LITERAL), Pattern.compile("Z]a", Pattern.LITERAL), Pattern.compile("[^b", Pattern.LITERAL), Pattern.compile("Y]b", Pattern.LITERAL), Pattern.compile("`][", Pattern.LITERAL)},
    // Local board 7
    {Pattern.compile("cde", Pattern.LITERAL), Pattern.compile("fgh", Pattern.LITERAL), Pattern.compile("ijk", Pattern.LITERAL), Pattern.compile("cfi", Pattern.LITERAL), Pattern.compile("dgj", Pattern.LITERAL), Pattern.compile("ehk", Pattern.LITERAL), Pattern.compile("cgk", Pattern.LITERAL), Pattern.compile("ige", Pattern.LITERAL)},
    // Local board 8
    {Pattern.compile("lmn", Pattern.LITERAL), Pattern.compile("opq", Pattern.LITERAL), Pattern.compile("rst", Pattern.LITERAL), Pattern.compile("lor", Pattern.LITERAL), Pattern.compile("mps", Pattern.LITERAL), Pattern.compile("nqt", Pattern.LITERAL), Pattern.compile("lpt", Pattern.LITERAL), Pattern.compile("rpn", Pattern.LITERAL)},
    // Local board 9
    {Pattern.compile("uvw", Pattern.LITERAL), Pattern.compile("xyz", Pattern.LITERAL), Pattern.compile("{}~", Pattern.LITERAL), Pattern.compile("ux{", Pattern.LITERAL), Pattern.compile("vy}", Pattern.LITERAL), Pattern.compile("wz~", Pattern.LITERAL), Pattern.compile("uy~", Pattern.LITERAL), Pattern.compile("{yw", Pattern.LITERAL)},
    // Global board
    {Pattern.compile("123", Pattern.LITERAL), Pattern.compile("456", Pattern.LITERAL), Pattern.compile("789", Pattern.LITERAL), Pattern.compile("147", Pattern.LITERAL), Pattern.compile("258", Pattern.LITERAL), Pattern.compile("369", Pattern.LITERAL), Pattern.compile("159", Pattern.LITERAL), Pattern.compile("357", Pattern.LITERAL)}
};
    
// WIN DETECTION METHOD
    
// Flag variables
static boolean flag0, flag1, flag2, flag3, flag4, flag5, flag6, flag7, flag8 = true;
    
static void findWinPatterns(String score) {
    for (int i = 0; i < winPatterns.length; i++) {
        for (Pattern pattern : winPatterns[i]) {
            Matcher matcher = pattern.matcher(score);
            boolean matchFound = matcher.find();
            if (matchFound) {
                System.out.println("3 in a row!" + " i = " + i);
// ... again, all the same stuff as before ...
            }
        }
    }
}
// MAIN METHOD HERE

这有效...完全与我的初始代码相同。这里的顺序仍然很重要,我真的不知道为什么。我真的差点认输并使用 org.apache.commons.lang3.StringUtils.containsAny().

只是快速解决一些问题:switch 块目前是一个评论,因为现在用 System.out.println 测试这个东西的功能更容易。它应该已经可以工作了,但它确实很笨重; 9 个布尔标志...如果您愿意,我也会在那里采纳建议。

但无论如何,我非常感谢您能帮助我解决这个难题。谢谢!

你的问题的核心似乎是:

Given a String of characters, how can I check that all those characters exist in another String

有几种方法可以做到这一点:

正则表达式:

用于检测字符串中所有 "abc" 的正则表达式是 "^(?=.*a)(?=.*b)(?=.*c).*"。您可以对正则表达式进行硬编码,也可以像这样从字符串构建它:

String search = "abc";
String target = "bxaxc"
String regex = "^" + search.replaceAll(".", "(?=.*[=10=])") + ".*";
if (target.matches(regex)) // true

使用集包含:

String search = "abc";
Set<Integer> searches = search.chars().boxed().collect(toSet());

String target = "bxaxc";
Set<Integer> targets = target.chars().boxed().collect(toSet());
if (searches.stream().allMatch(target::contains)) // true

我希望第二个选项的性能稍微快一些,但是使用第一个(正则表达式)选项进行比较的代码更容易理解。

我将这些选项之一或您自己的选项编织到您的项目中。