Как сравнить элементы в pygame.Surface?

Я хотел создать игру пазл, где нужно собрать все кусочки экрана правильно и после того как картинка собрана правильно, игра завершится.

Но есть одна проблема: игра не завершается, потому что при сравнении координат кусков, они разные.

import pygame
import pyautogui
import random

screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")

pygame.init()

screen_width, screen_height = pyautogui.size()
screen = pygame.display.set_mode((screen_width, screen_height), pygame.FULLSCREEN)

rows = 2
cols = 2
piece_width = screen_width // cols
piece_height = screen_height // rows

key = 0
pieces = []

for y in range(rows):
    for x in range(cols):
        piece = pygame.Surface((piece_width, piece_height))
        piece.blit(pygame.image.load("screenshot.png"), (0, 0),
                   (x * piece_width, y * piece_height, piece_width, piece_height))
        pieces.append(piece)

print(pieces)

for piece in pieces:
    pygame.draw.rect(piece, (0, 0, 0), pygame.Rect(0, 0, piece_width, piece_height), 2)

random.shuffle(pieces)

selected_piece = None
move_x, move_y = 0, 0

def get_initial_coordinates(cols, rows, piece_width, piece_height):
    initial_coords = {}
    for i in range(rows):
        for j in range(cols):
            initial_coords[i * cols + j] = (j * piece_width, i * piece_height)
    return initial_coords

initial_coords = get_initial_coordinates(cols, rows, piece_width, piece_height)

def check_completed_puzzle(pieces, initial_coords):
    for i, piece in enumerate(pieces):
        x = i % cols
        y = i // cols
        if piece.get_rect().topleft != initial_coords[i]:
            return False
    return True

running = True
selected_piece = None
initial_coords = get_initial_coordinates(cols, rows, piece_width, piece_height)

while running:
    move_x, move_y = 0, 0
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False
            elif event.key == pygame.K_UP:
                move_x, move_y = 0, -1
            elif event.key == pygame.K_DOWN:
                move_x, move_y = 0, 1
            elif event.key == pygame.K_LEFT:
                move_x, move_y = -1, 0
            elif event.key == pygame.K_RIGHT:
                move_x, move_y = 1, 0
        if event.type == pygame.MOUSEBUTTONDOWN:
            x, y = pygame.mouse.get_pos()
            col = x // piece_width
            row = y // piece_height
            selected_piece = row * cols + col

    if selected_piece is not None:
        x = selected_piece % cols
        y = selected_piece // cols
        new_x = x + move_x
        new_y = y + move_y
        new_index = new_y * cols + new_x

        if 0 <= new_x < cols and 0 <= new_y < rows and abs(move_x) + abs(move_y) == 1:
            pieces[selected_piece], pieces[new_index] = pieces[new_index], pieces[selected_piece]
            selected_piece = new_index  

            if check_completed_puzzle(pieces, initial_coords):
                print("Вы собрали пазл!")
                running = False

    screen.fill((0, 0, 0))
    for i, piece in enumerate(pieces):
        x = i % cols
        y = i // cols
        screen.blit(piece, (x * piece_width, y * piece_height))

    if selected_piece is not None:
        x = selected_piece % cols
        y = selected_piece // cols
        pygame.draw.rect(screen, (0, 0, 255), pygame.Rect(x * piece_width, y * piece_height, piece_width, piece_height), 2)

    pygame.display.flip()

pygame.quit()

При попытке сравнить списки, содержащие тип данных pygame.Surface до и после перемешивания, они оказывались одинаковыми(True):

P1 = pieces
random.shuffle(pieces)
P2 = pieces
print(P1 == P2)

Даже пытался узнать и сравнить координаты пазлов вручную:

for i, piece in enumerate(pieces):
    x = i % cols
    y = i // cols
    print(f"Кубик {i} находится в координатах x:{x*piece_width}, y:{y*piece_height}")

random.shuffle(pieces)

for i, piece in enumerate(pieces):
    x = i % cols
    y = i // cols
    print(f"Кубик {i} находится в координатах x:{x*piece_width}, y:{y*piece_height}")

Координаты были одинаковыми, как будто ничего и не произошло.


Ответы (1 шт):

Автор решения: S. Nick

Sorry, я не вникал в вашу логику. Я просто решил добавить что-то (y, x) для сравнения в список pieces. Попробуйте.

import pygame
import pyautogui
import random
import copy                                                          # +++

screenshot = pyautogui.screenshot()
screenshot.save("screenshot.png")

pygame.init()

screen_width, screen_height = pyautogui.size() 
screen = pygame.display.set_mode(
    (screen_width, screen_height), pygame.FULLSCREEN)

rows = 2
cols = 2
piece_width = screen_width // cols
piece_height = screen_height // rows

key = 0
pieces = []

for y in range(rows):
    for x in range(cols):
        piece = pygame.Surface((piece_width, piece_height))
        piece.blit(
            pygame.image.load("screenshot.png"), 
            (0, 0),
            (x * piece_width, y * piece_height, piece_width, piece_height)
        )
# +++        
        pieces.append([piece, (y, x)])                               # +++ , (y, x)
# +++    v vvv
for piece, y_x  in pieces:
    pygame.draw.rect(
        piece, 
        (222, 0, 0), 
        pygame.Rect(0, 0, piece_width, piece_height), 
        2
    )
    
# +++
P1 = copy.deepcopy(pieces)                                           # +++

random.shuffle(pieces)


selected_piece = None
move_x, move_y = 0, 0

def get_initial_coordinates(cols, rows, 
                            piece_width, piece_height):
    initial_coords = {}
    for i in range(rows):
        for j in range(cols):
            initial_coords[i * cols + j] = (
                j * piece_width, i * piece_height)
    return initial_coords

initial_coords = get_initial_coordinates(
    cols, rows, piece_width, piece_height)

def check_completed_puzzle(pieces, initial_coords):
    '''
    for i, piece in enumerate(pieces):
        x = i % cols
        y = i // cols
        if piece.get_rect().topleft != initial_coords[i]:
            return False
    return True        
    '''
# +++                                                                # +++
    if P1[0][1] == pieces[0][1] and P1[1][1] == pieces[1][1] and \
       P1[2][1] == pieces[2][1] and P1[3][1] == pieces[3][1] :       # +++
        return True
    return False

running = True
selected_piece = None
initial_coords = get_initial_coordinates(cols, rows, piece_width, piece_height)

while running:
    move_x, move_y = 0, 0

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
            
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False
            elif event.key == pygame.K_UP:
                move_x, move_y = 0, -1
            elif event.key == pygame.K_DOWN:
                move_x, move_y = 0, 1
            elif event.key == pygame.K_LEFT:
                move_x, move_y = -1, 0
            elif event.key == pygame.K_RIGHT:
                move_x, move_y = 1, 0
        if event.type == pygame.MOUSEBUTTONDOWN:
            x, y = pygame.mouse.get_pos()
            col = x // piece_width
            row = y // piece_height
            selected_piece = row * cols + col

    if selected_piece is not None:
        x = selected_piece % cols
        y = selected_piece // cols
        new_x = x + move_x
        new_y = y + move_y
        new_index = new_y * cols + new_x

        if 0 <= new_x < cols and 0 <= new_y < rows and \
            abs(move_x) + abs(move_y) == 1:
            pieces[selected_piece], pieces[new_index] = pieces[new_index], \
                pieces[selected_piece]
            selected_piece = new_index  
# ----------------------------------> ?????????????????????? <------------
            if check_completed_puzzle(pieces, initial_coords):
                print("Вы собрали пазл!")
                running = False

    screen.fill((0, 0, 0))
    for i, piece in enumerate(pieces):
#        print(f'y_x ==== {piece[1]} ---- {i}') #
        x = i % cols
        y = i // cols
# ----------------------> v <----------------------------------------------        
        screen.blit(piece[0], (x * piece_width, y * piece_height))

    if selected_piece is not None:
        x = selected_piece % cols
        y = selected_piece // cols
        pygame.draw.rect(
            screen, 
            (0, 222, 255), 
            pygame.Rect(
                x * piece_width, 
                y * piece_height, 
                piece_width, 
                piece_height), 
            2
        )

    pygame.display.flip()

pygame.quit()

input("Игра закончена. Нажмите Enter.")

введите сюда описание изображения

введите сюда описание изображения

→ Ссылка