如何在单击它们时将所有无用的单元格着色?

问题描述

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

以下是其工作方式的演示:

enter image description here

如果您不知道,该程序将允许用户选择2个相邻的单元格,然后选择 两个单元均匀地分布在两个单元中。如果两个数字之和为奇数, 首先,编号最大的单元将比另一个大。

用户第一次选择一个单元格时,将仅突出显示与该单元格至少相差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)
    
    def draw(self):
        pygame.draw.rect(wn,self.color,self.rect)
        text = font.render(str(self.num),True,(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)
                            Box.square = square
                            Box.color((255,140))
                        else:
                            if square in Box.Box():
                                Box.clicked.append(square)
                            if square == Box.clicked[0]:
                                Box.color((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))
                            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 j )的所有相邻索引元组( l k ) :

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+2)):
                for l in range(max(0,j+2)):
                    if i != k or j != l:
                        adjacent.append((k,l))

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

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

    # [...]