如何递归检查一个拼字游戏中的答案
作为一个练习,我一直在尝试用Python制作一个没有图形界面的拼字游戏。到目前为止,用户可以输入一个棋盘的大小(比如4x4、5x5等)。然后字母的“数组”会出现,用户可以输入他们认为有效的单词。
我想通过使用递归函数来检查输入的单词是否有效。在小棋盘上,我的解决方案似乎运行得很好。然而在较大的棋盘上,开头相似且有多个路径的单词却无法识别。我觉得这可能是因为我的函数最后部分无法在当前路径结束时回退得足够远,以找到正确的单词。
这是我目前的代码:
def isAdjacent(word, wordLetter, possibleStarts, arrayDict, currWord, start):
#'word' is the word entered. 'wordLetter' is the current letter being looked for.
#'possibleStarts' is a list of tuples of the possible starting locations and subsequent positions of each found letter.
#'arrayDict' is a dictionary associating each position ((0,1), etc) with a game letter.
#'currWord' is used to check whether or not a word has been found.
#'start' is the tuple in possibleStarts that should be used.
if currWord == word:
return 1
x = possibleStarts[start][0]
y = possibleStarts[start][1]
arrayDict[x,y] = 0
optionsList = [(x - 1, y - 1), (x - 1, y), (x - 1, y + 1), (x, y - 1), (x, y + 1), (x + 1, y - 1), (x + 1, y), (x + 1, y + 1)]
newStarts = []
count = 0
count2 = 0
for option in optionsList:
count += 1
if option in arrayDict:
if arrayDict[option] == word[wordLetter]:
if count2 < 1:
currWord += word[wordLetter]
arrayDict[option] = 0
count2 += 1
newStarts.append(option)
if count == 8 and newStarts:
return isAdjacent(word, wordLetter + 1, newStarts, arrayDict, currWord, start)
try:
if currWord != word:
if wordLetter > 2:
return isAdjacent(word, wordLetter - 1, possibleStarts, arrayDict, currWord[:-1], start - 1)
else:
return isAdjacent(word, wordLetter, possibleStarts, arrayDict, currWord, start - 1)
except:
pass
我相信问题至少部分出在函数最后的try块里。如果单词不太长或者可能性不太多,它就能正常工作。例如,尝试在下面的棋盘中找到“raws”,即使它确实存在,也不会成功:
W T S V
A X A H
S R T S
A B A W
我确信这可以通过一个相对简单的递归函数来完成,但经过很多小时的努力,我还是迷失了方向。哦,我不想提前生成所有可能的单词。这个练习的目标是使用递归来查找输入的单词。
任何帮助都非常感谢!
1 个回答
0
这个练习挺有意思的,我试着做了一下。下面是我的代码,所以算是提前剧透了。关于一些一般性的建议:
- 把代码拆分成更小的部分——一个函数搞定所有事情是行不通的。
- 在做递归的时候,先找出基本情况,也就是函数什么时候不需要再递归了。
- 让每个子函数只知道它需要知道的内容。
就这些了。我对Boggle的完整规则有点生疏,不太确定你们整个过程在做什么,但这是我想到的:
def paths(grid, x, y, l):
"""Returns a list of positions that the required letter is at"""
positions = [(x - 1, y - 1), (x - 1, y), (x - 1, y + 1), (x, y - 1), (x, y + 1), (x + 1, y - 1), (x + 1, y), (x + 1, y + 1)]
return [p for p in positions if p in grid and grid[p] == l]
def matchWord(grid, pos, word):
"""Returns true if the word was found in the grid starting from pos"""
if word == "" : return True
pos_paths = paths(grid, pos[0], pos[1], word[0])
if pos_paths == [] : return False
return any(matchWord(grid, the_pos, word[1:]) for the_pos in pos_paths)
def wordInGrid(grid, word):
"""returns true if the word is in the grid"""
return any(matchWord(grid, key, word[1:]) for (key, val) in dict.iteritems(grid) if val == word[0])
gr_dict = {(0, 1): 'T', (1, 2): 'A', (3, 2): 'A', (0, 0): 'W', (3, 3): 'W', (3, 0): 'A', (3, 1): 'B', (2, 1): 'R', (0, 2): 'S', (2, 0): 'S', (1, 3): 'H', (2, 3): 'S', (2, 2): 'T', (1, 0): 'A', (0, 3): 'V', (1, 1): 'X'}
print wordInGrid(gr_dict, "RATS")
print wordInGrid(gr_dict, "WASABATAS")