如何使我的递归函数返回以继续递归其他单元格

时间:2020-11-06 21:24:36

标签: python recursion pygame

我正在使用Pygame进行单词查找。 该程序循环遍历网格中的每个单元格, 在每个单元上,它在其上运行递归函数以查看是否 它属于一系列单元以组成一个单词。

到目前为止,我的程序只工作一半。说网格看起来像这样:

enter image description here

我的程序将打印FOUND 3次,所以看起来不错。
但是如果网格看起来像这样:

enter image description here

它只会打印一次FOUND。原因是因为一旦程序找到了一个可以进行一系列单元格的相邻单元格, 它会沟渠附近那个小区的其他可能性。

在递归完成后,如何使程序返回其他相邻的单元格?

这是我定义递归函数的方式:

    def adj(self, cell, idx, lst, wrd):
        x, y = self.cells.index(cell) // self.rows, self.cells.index(cell) % self.rows
        y1 = x - 1 if x else 0
        y2 = self.rows + 2 if x > self.rows + 2 else x + 2
        x1 = y - 1 if y else 0
        x2 = self.cols + 2 if y > self.cols + 2 else y + 2
        adjs = [cell for row in self.grid[y1:y2] for cell in row[x1:x2] if cell != self.grid[x][y]]
        for cell in adjs:
            if len(wrd) > idx:
                if cell.text == wrd[idx]:
                    idx += 1
                    lst.append(cell)
                    self.adj(cell, idx, lst, wrd)

这是我的称呼方式:

                for cell in grid.cells:
                    lst = [cell]
                    grid.adj(cell, 1, lst, word)
                    if ''.join([c.text for c in lst]) == word:
                        print("FOUND")

我的代码:

import pygame
pygame.font.init()

wn = pygame.display.set_mode((600, 600))


class Cell():
    def __init__(self, x, y, s, color=(0, 0, 0)):
        self.input_box = pygame.Rect(x, y, s, s)
        self.x = x
        self.y = y
        self.s = s
        self.color_inactive = color
        self.color_active = pygame.Color('purple')
        self.color = self.color_inactive
        self.text = ' '
        self.active = False
        self.font = pygame.font.Font(None, s)

    def check_status(self, pos):
        if self.input_box.collidepoint(pos):
            self.active = not self.active
        else:
            self.active = False
        self.color = self.color_active if self.active else self.color_inactive

    def type(self, char):
        if self.active:
            if char and char.lower() in 'abcdefghijklmnopqrstuvwxyz ':
                self.text = char

    def draw(self):
        txt = self.font.render(self.text, True, self.color)
        x, y = self.x+(self.s-txt.get_width())//2, self.y+(self.s-txt.get_height())*5//7
        wn.blit(txt, (x, y))
        pygame.draw.rect(wn, self.color, self.input_box, 2)


class Grid():
    def __init__(self, x, y, cols, rows, size, color=(0, 0, 0)):
        self.grid = [[Cell(i*size+x, j*size+y, size) for i in range(cols)] for j in range(rows)]
        self.cells = [cell for row in self.grid for cell in row]
        self.rows = rows
        self.cols = cols

    def check_status(self, pos):
        for cell in self.cells:
            cell.check_status(pos)

    def type(self, char):
        for cell in self.cells:
            cell.type(char)

    def adj(self, cell, idx, lst, wrd):
        x, y = self.cells.index(cell) // self.rows, self.cells.index(cell) % self.rows
        y1 = x - 1 if x else 0
        y2 = self.rows + 2 if x > self.rows + 2 else x + 2
        x1 = y - 1 if y else 0
        x2 = self.cols + 2 if y > self.cols + 2 else y + 2
        adjs = [cell for row in self.grid[y1:y2] for cell in row[x1:x2] if cell != self.grid[x][y]]
        for cell in adjs:
            if len(wrd) > idx:
                if cell.text == wrd[idx]:
                    idx += 1
                    lst.append(cell)
                    self.adj(cell, idx, lst, wrd)


    def draw(self):
        for cell in self.cells:
            cell.draw()


grid = Grid(50, 50, 10, 10, 32)
word = 'CAT'

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            grid.check_status(event.pos)
        elif event.type == pygame.KEYDOWN:
            grid.type(event.unicode)
            if event.key == pygame.K_RETURN:
                for cell in grid.cells:
                    lst = [cell]
                    grid.adj(cell, 1, lst, word)
                    if ''.join([c.text for c in lst]) == word:
                        print("FOUND")

                        
    wn.fill((255, 255, 200))
    grid.draw()
    pygame.display.flip()

1 个答案:

答案 0 :(得分:2)

实际的问题是您只有一个列表。如果要查找多个单词,则需要一个列表列表:

if event.key == pygame.K_RETURN:
    for cell in grid.cells:
        lstlst = [[cell]]
        grid.adj(cell, 1, lstlst, word)
        for lst in lstlst:
            if ''.join([c.text for c in lst]) == word:
                print("FOUND")

识别出新字符后,您需要复制列表列表中的最后一个列表:

taillst = lstlst[-1]
lst = taillst[:]

将新单元格添加到副本,然后将副本添加到列表列表的末尾:

lst.append(cell)
lstlst.append(lst)

不要递增idx,而是将idx + 1传递到下一个递归级别:

self.adj(cell, idx+1, lstlst, wrd)

完整方法adj

class Grid():
    # [...]

    def adj(self, cell, idx, lstlst, wrd):
        x, y = self.cells.index(cell) // self.rows, self.cells.index(cell) % self.rows
        y1 = x - 1 if x else 0
        y2 = self.rows + 2 if x > self.rows + 2 else x + 2
        x1 = y - 1 if y else 0
        x2 = self.cols + 2 if y > self.cols + 2 else y + 2
        adjs = [cell for row in self.grid[y1:y2] for cell in row[x1:x2] if cell != self.grid[x][y]]
        taillst = lstlst[-1]
        for cell in adjs:
            if len(wrd) > idx:
                if cell.text == wrd[idx]:
                    lst = taillst[:]
                    lst.append(cell)
                    lstlst.append(lst)
                    self.adj(cell, idx+1, lstlst, wrd)

以下模式

返回以下3个匹配项的6个列表:

['C']
['C', 'A']
['C', 'A', 'T']
['C', 'A', 'T']
['C', 'A']
['C', 'A', 'T']