单击它们时如何遮挡所有无用的单元格?

How to shade all the cells that will be useless when you click on them?

我使用 Pygame.

制作了一个小游戏 (令人费解的 StackExchange 助手)

这是一个关于它如何工作的演示:

如果你分不清,程序允许用户 select 2 个相邻的单元格,然后是 两个单元格均匀分布在两个单元格之间。如果两个数的和是奇数, 排在第一位的数字最大的单元格将比另一个大。

当用户第一个 select 一个单元格时,只有与该单元格至少相差 2 的相邻单元格才会突出显示。

我想知道如何为所有没有相邻单元格的单元格添加灰色阴影,这些单元格的数字至少与该单元格相差 2。

换句话说,如何为单元格添加阴影,当您单击它们时,将没有相邻的单元格,您可以单击以更改其编号。

我的代码(一直向下滚动以查看注释,这是我尝试使其工作但失败的方式):

import pygame

# You can change the grid & size to whatever you like
grid = [[7, 24, 12, 8, 11],
        [13, 21, 3, 20, 19],
        [10, 22, 15, 2, 9],
        [23, 1, 6, 16, 17],
        [5, 25, 14, 4, 18]]

size = 60

pygame.init()
pygame.font.init()

font = pygame.font.SysFont("Arial", size-10)
wn = pygame.display.set_mode((600, 600))

class Square():
    def __init__(self, pos, num):
        self.x = pos[0] * size
        self.y = pos[1] * size
        self.num = num
        self.color = (255, 255, 255)
        self.rect = pygame.Rect(self.x, self.y, size-5, size-5)

    def clear(self):
        self.color = (255, 255, 255)
    
    def draw(self):
        pygame.draw.rect(wn, self.color, self.rect)
        text = font.render(str(self.num), True, (0, 0, 0))
        if len(str(self.num)) == 1:
            wn.blit(text, (self.x+size*.25, self.y*.98))
        else:
            wn.blit(text, (self.x+size*.055, self.y*.98))
        


class Box():

    def __init__(self, grid, square=None):
        self.square = square
        self.grid = grid
        self.clicked = []

    def box(self): # Returns a list of all adjancent squares that can change the number of the selected square
        x, y = self.square.x//size, self.square.y//size
        y1 = x-1 if x else 0
        y2 = len(self.grid)+2 if x > len(self.grid)+2 else x+2
        x1 = y-1 if y else 0
        x2 = len(self.grid[0])+2 if y > len(self.grid[0])+2 else y+2
        b = []
        for r in self.grid[y1:y2]:
            for c in r[x1:x2]:
                if abs(c.num - self.grid[x][y].num) > 1:
                    b.append(c)
                elif c != self.square:
                    c.clear()
        return b

    def color(self, color):
        for square in self.box():
            square.color = color

    def clear(self):
        for c in self.clicked:
            c.clear()
        self.clicked.clear()

def avg(n1, n2):
    n = n1 + n2
    if n % 2:
        if n1 > n2:
            return n // 2 + 1, n // 2
        return n // 2, n // 2 + 1
    return n // 2, n // 2


squares = [[Square((i, j), col) for j, col in enumerate(row)] for i, row in enumerate(grid)]
box = Box(squares)
box2 = Box(squares)
total = 0

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            for row in squares:
                for square in row:
                    if square.rect.collidepoint(pygame.mouse.get_pos()):
                        if not box.clicked:
                            box.clicked.append(square)
                            square.color = (140, 255, 255)
                            box.square = square
                            box.color((255, 255, 140))
                        else:
                            if square in box.box():
                                box.clicked.append(square)
                            if square == box.clicked[0]:
                                box.color((255, 255, 255))
                                box.clear()
                        if len(box.clicked) == 2:
                            total += 1
                            print(total)
                            box.clicked[0].num, box.clicked[1].num = avg(box.clicked[0].num, box.clicked[1].num)
                            box.color((255, 255, 255))
                            box.clear()

    for row in squares:
        for square in row:
#            temp = Box(squares, square)
#            if not temp.box():
#                square.color = (140, 140, 140)
#            del(temp)
            square.draw()

    pygame.display.update()


使用嵌套循环和索引遍历网格的所有单元格 (i, j):

for i in range(len(squares)):
    for j in range(len(squares[i])):
        # [...]

求一个单元格(i[=36=)的所有相邻索引元组(l,k) ], j):

adjacent = []
for k in range(max(0,i-1), min(len(squares), i+2)):
    for l in range(max(0,j-1), min(len(squares[k]), j+2)):
        if i != k or j != l:
            adjacent.append((k, l))

如果单元格 (i, j) 没有邻居 (not any()) (l, k) 其中差异至少为 2:

if not any((k, l) for (k, l) in adjacent if abs(squares[i][j].num - squares[k][l].num) > 1):
    squares[i][j].color = (140, 140, 140)

完成嵌套循环

while True:
    # [...]

    for i in range(len(squares)):
        for j in range(len(squares[i])):

            adjacent = []
            for k in range(max(0,i-1), min(len(squares), i+2)):
                for l in range(max(0,j-1), min(len(squares[k]), j+2)):
                    if i != k or j != l:
                        adjacent.append((k, l))

            if not any((k, l) for (k, l) in adjacent if abs(squares[i][j].num - squares[k][l].num) > 1):
                 squares[i][j].color = (140, 140, 140)
            elif squares[i][j].color == (140, 140, 140):
                square.clear()

    for row in squares:
        for square in row:
            square.draw()

    # [...]