我需要在给定初始网格和单词的情况下解决填字游戏(单词可以多次使用或根本不使用).
初始网格如下所示:
++_+++
+____+
___+__
+_++_+
+____+
++_+++
这是一个单词列表示例:
pain
nice
pal
id
任务是填充占位符(水平或垂直长度 > 1)像那样:
++p+++
+pain+
pal+id
+i++c+
+nice+
++d+++
任何正确的解都是可以接受的,并且保证有解。
为了开始解决问题,我将网格存储为 2-dim。 char 数组,我按单词的长度将单词存储在集合列表中:List<Set<String>> words
,因此例如长度为 4 的字可以通过以下方式访问words.get(4)
然后我从网格中提取所有占位符的位置并将它们添加到占位符列表(堆栈)中:
class Placeholder {
int x, y; //coordinates
int l; // the length
boolean h; //horizontal or not
public Placeholder(int x, int y, int l, boolean h) {
this.x = x;
this.y = y;
this.l = l;
this.h = h;
}
}
该算法的主要部分是solve()
method:
char[][] solve (char[][] c, Stack<Placeholder> placeholders) {
if (placeholders.isEmpty())
return c;
Placeholder pl = placeholders.pop();
for (String word : words.get(pl.l)) {
char[][] possibleC = fill(c, word, pl); // description below
if (possibleC != null) {
char[][] ret = solve(possibleC, placeholders);
if (ret != null)
return ret;
}
}
return null;
}
功能fill(c, word, pl)
仅返回一个新的填字游戏,其中当前单词写在当前占位符上pl. If word不兼容pl,则函数返回 null。
char[][] fill (char[][] c, String word, Placeholder pl) {
if (pl.h) {
for (int i = pl.x; i < pl.x + pl.l; i++)
if (c[pl.y][i] != '_' && c[pl.y][i] != word.charAt(i - pl.x))
return null;
for (int i = pl.x; i < pl.x + pl.l; i++)
c[pl.y][i] = word.charAt(i - pl.x);
return c;
} else {
for (int i = pl.y; i < pl.y + pl.l; i++)
if (c[i][pl.x] != '_' && c[i][pl.x] != word.charAt(i - pl.y))
return null;
for (int i = pl.y; i < pl.y + pl.l; i++)
c[i][pl.x] = word.charAt(i - pl.y);
return c;
}
}
这是完整的代码雷克斯特 http://rextester.com/MEYRW1661.
问题是我的回溯算法不能很好地工作。假设这是我的初始网格:
++++++
+____+
++++_+
++++_+
++++_+
++++++
这是单词列表:
pain
nice
我的算法会把这个词pain
垂直,但当意识到这是一个错误的选择时,它会回溯,但到那时初始网格将已经更改并且占位符的数量将减少。您认为如何修复该算法?