【问题标题】:How to split a 2D array in different sized pieces for a crossword?如何将二维数组拆分为不同大小的拼字游戏?
【发布时间】:2017-03-21 21:21:08
【问题描述】:

我正在尝试使用填字游戏的生成器,但是当需要将其拆分为不同的部分时,我遇到了困难。我有一个二维数组,我在其中存储这样的填字游戏:

int SIZE = 10; //This can be higher for bigger crosswords
Character[][] crossword = new Character[SIZE][SIZE];

然后我在这个填字游戏中添加一些单词,例如以以下数组结尾(. = 空方格):

..........
..........
..C...H...
..A...O...
..TIGER...
......S...
...DOVE...
..........
..........
..........

如何拆分这个二维数组,以便最终得到包含至少 2 个字母但不包含整个单词的片段。字母也必须水平或垂直彼此相邻,但不能对角。例如,我最终可以得到以下部分:

C    TIG    H    ER    DOV
A           O     S
                  E

以下部分无效,因为字母不是水平或垂直相邻的。

  O
GE
  S

我的第一次尝试是通过以下方式进行拆分:

int chunksize = 2; //This should vary depending on how big the pieces should be
List<Character[][]> subArrays = new ArrayList<>();
for(int i = 0; i < SIZE; i += chunksize){
    for(int j = 0; j < SIZE; j += chunksize){
        Character[][] sub = new Character[chunksize][chunksize];
        sub[0][0] = crossword[i][j];
        sub[0][1] = crossword[i][j + 1];
        sub[1][0] = crossword[i + 1][j];
        sub[1][1] = crossword[i + 1][j + 1];
        if(sub[0][0] != null || sub[0][1] != null || sub[1][0] != null || sub[1][1] != null){
            subArrays.add(sub);
        }
    }
}

但是,这可能会创建仅包含一个字母的片段或字母不相邻的片段。我不知道我应该如何解决这个问题,所以我来这里寻求帮助。

【问题讨论】:

  • chunksize 到底是什么?你能解释一下你想用嵌套的 for 循环做什么吗?
  • chunksize 是我试图说出的碎片应该有多大。如果是 2,那么我一次检查纵横字谜 2 个方格,水平和垂直。嵌套的 for 循环用于循环遍历 2D 数组中的行和列。但是,这种方法(就像现在一样)将返回格式错误的片段,我不知道如何更改它(或者可能只是添加更多检查)以使其创建具有正确格式的片段。最后的空检查是检查创建的块(片)是否包含字母。
  • 为什么要拆分阵列?我明白你的问题是什么,但不知道你想用这个实现什么。
  • 我正在尝试创建一个填字游戏生成器。所以如果我有完整的填字游戏,我想把它分成更小的部分。然后将这些片段提供给将尝试将所有单词组合在一起的用户。我没有手动执行此操作,而是尝试编写一个程序来执行此操作。例如,假设我们只有 TIGER 这个词。然后我想把它分成两部分:TIG 和 ER。然后将这些碎片提供给用户,用户将单击并拖动(或在 android 上触摸并拖动)以将这些碎片组合在一起并创建单词 TIGER。
  • 所以chunksize 对于ER 是2,对于TIG 是3?

标签: java android arrays algorithm


【解决方案1】:

我建议你做的是将每一行和每一列转换成它自己的字符串。

例如: 前 3 行

..........
..........
..C...H...

前 3 列

..........
..........
..CAT.....

例如,您可以通过使用 for 循环来做到这一点:

for(int x = 0; x < SIZE; x++){
    //Loop through rows and columns.
    //(eg:crossword[x][y] in this loop will extract a row of values)
    //(eg:crossword[y][x] in this loop will extract a column of values)
    for(int y = 0; y < SIZE; y++){
        //Code to build each row/column string
    }
    //Add extracted Strings to an ArrayList?
}

获得这些字符串后,您可以使用以下方法拆分它们:(假设 . 仍然是您的分隔符)

s.split("\\.");

这将为您留下每行和每列的字符串数组

中提取C和H作为单独的字符串
..........
..........
..C...H...

中提取 CAT 作为单个字符串
..........
..........
..CAT.....

这应该允许您根据块大小检查它们的长度并返回您想要的组合。

希望我已经正确理解了这个问题,或者它至少给了你一些想法,可以用来开发你正在寻找的解决方案。

【讨论】:

    【解决方案2】:

    多米诺骨牌包装

    以下方法创建尽可能多的 size-2 块。之后,任何剩余的单个字母都需要以某种方式附加到相邻块 - 例如,通过随机选择相邻块之一。

    创建一个图形,其中每个字母占据的位置都有一个顶点,任何一对垂直或水平相邻的字母位置之间都有一条边。现在在这个图上计算一个maximum matching:这会选择一个最大尺寸的边子集,这样没有一个顶点会入射到一个以上的边上。这些边对应大小为 2 的块。

    如果您将网格想象成棋盘,您会注意到每个正方形不是白色就是黑色,并且没有边连接两个白色单元格或两个黑色单元格:这意味着该图是二分的,这反过来意味着您可以使用 O(|E|*sqrt(|V|))-time Hopcroft-Karp algorithm,它比 Edmonds 的一般图算法更快更简单。

    【讨论】:

    • 我一个字都听不懂,但是……哇!
    猜你喜欢
    • 2022-01-15
    • 2017-11-08
    • 1970-01-01
    • 2011-07-24
    • 1970-01-01
    • 2016-03-15
    • 2016-08-10
    • 2022-07-06
    • 1970-01-01
    相关资源
    最近更新 更多