我正在尝试实现这个算法:http://www.cs.cmu.edu/afs/cs/academic/class/15451-s06/www/lectures/scrabble.pdf但我无法弄清楚这些锚方格到底是什么(首先在3.1.2中提到然后在3.3中提到)。
我知道他们的候选人都是与董事会成员相邻的空方格,但不知道我应该选择哪一个。
另外,我不知道为什么左边部分的所有方格都有琐碎的交叉检查(意味着每个字母都可以放在那里),锚点总是有非平凡的交叉检查。这种情况怎么样:
_._._._
_._.x.A
_._._._
_是空方,x是锚,A是板上已有的字母 - 为什么在这种情况下我需要检查x进行交叉检查,显然不需要它?
答案 0 :(得分:2)
根据拼字游戏的规则,你的词必须连接到 - 或者锚定 - 在棋盘上的现有单词。现在,当我们一次查看一行时,有三种类型的锚点:
如果我们在与上方或下方的字母相邻的锚点上放置一个字母,我们也必须用这些字母组成一个有效的单词,从而对该锚点允许的字母施加额外的约束。当使用与当前行中的字母相邻的锚点(并且仅那些)时,我们可以放置在该图块上的字母仅受我们将在当前行中形成的单词的约束,因此,除了实际的字形成算法之外,不需要任何检查。
这意味着,在您的示例中,实际上对于x
上的字母没有其他限制。只需找到从x
向左延伸的前缀,即可生成带有A
字母的有效字词(或更长的前缀)。
您可能还想查看Udacity课程“Design of Computer Programs”,在那里他们讨论单元6中的拼字游戏求解算法。
答案 1 :(得分:0)
我创建了一个基于洪水填充的算法来收集所有接触我们刚刚掉落的瓦片,其中一个必须与中心瓦片相交才能使游戏有效。
算法从您丢弃的每个图块开始,然后检查每个周围的正方形是否有图块,如果图块存在于特定方向,则会将其添加到集合中,并递归地对触摸此新图块的每个图块执行相同操作,如果没有瓷砖,它将退出该功能。当我们从所播放的字母中向所有方向用尽瓷砖时,递归结束。
func getFilledSquare(c: Coordinate) -> Square? {
return squares
|> { s in filter(s) { $0.c == c && $0.tile != nil } }
|> { s in first(s) }
}
func getAdjacentFilledSquares(c: Coordinate?, vertically v: Bool, horizontally h: Bool, original: Square, inout output: Set<Square>) {
// We may hit the original square several times in different directions, so we allow it through multiple times
if let coord = c, sq = getFilledSquare(coord) where sq == original || !output.contains(sq) {
output.insert(sq)
if h {
getAdjacentFilledSquares(coord.next(.Horizontal, d: 1, b: self), vertically: v, horizontally: h, original: original, output: &output)
getAdjacentFilledSquares(coord.next(.Horizontal, d: -1, b: self), vertically: v, horizontally: h, original: original, output: &output)
}
if v {
getAdjacentFilledSquares(coord.next(.Vertical, d: 1, b: self), vertically: v, horizontally: h, original: original, output: &output)
getAdjacentFilledSquares(coord.next(.Vertical, d: -1, b: self), vertically: v, horizontally: h, original: original, output: &output)
}
}
}
它是开源的,这个方法叫做getAdjacentFilledSquares(我知道有点冗长)。我的回购在这里:https://github.com/ChrisAU/Locution?files=1