|
| 1 | +import pygame |
| 2 | +import random |
| 3 | +import sys |
| 4 | + |
| 5 | +class SlidingPuzzleGame: |
| 6 | + def __init__(self): |
| 7 | + pygame.init() |
| 8 | + pygame.font.init() |
| 9 | + self.largura = 1280 |
| 10 | + self.altura = 720 |
| 11 | + self.tela = pygame.display.set_mode((self.largura, self.altura)) # Janela com resolução fixa |
| 12 | + pygame.display.set_caption("Puzzle Deslizante") |
| 13 | + self.relogio = pygame.time.Clock() |
| 14 | + self.fps = 30 |
| 15 | + |
| 16 | + # Estados: "menu", "game", "game_over" |
| 17 | + self.estado = "menu" |
| 18 | + |
| 19 | + # Variáveis para dificuldade; o score final é fixo conforme dificuldade. |
| 20 | + self.board_size = None # Será definido pelo jogador (3, 4 ou 5) |
| 21 | + self.score = 0 |
| 22 | + |
| 23 | + # Tabuleiro (lista de listas) e posição do espaço vazio (0) |
| 24 | + self.board = None |
| 25 | + self.blank_pos = None # (row, col) |
| 26 | + |
| 27 | + # Fontes |
| 28 | + self.fonte_menu = pygame.font.SysFont(None, 60) |
| 29 | + self.fonte_game = pygame.font.SysFont(None, 48) |
| 30 | + self.fonte_moves = pygame.font.SysFont(None, 36) |
| 31 | + |
| 32 | + # Paleta de cores (tons de azul e cinza suaves) |
| 33 | + self.cor_fundo = (200, 230, 255) # Azul claro para o fundo |
| 34 | + self.cor_celula = (235, 200, 255) # Azul bem claro para as células |
| 35 | + self.cor_texto = (50, 50, 50) # Cinza escuro para o texto |
| 36 | + self.cor_grid = (150, 150, 200) # Azul acinzentado para a grade |
| 37 | + |
| 38 | + # Tamanho das células (definido após a escolha de dificuldade) |
| 39 | + self.cell_size = None |
| 40 | + |
| 41 | + def gerar_tabuleiro_solved(self, n): |
| 42 | + board = [[col + row * n + 1 for col in range(n)] for row in range(n)] |
| 43 | + board[n-1][n-1] = 0 |
| 44 | + return board |
| 45 | + |
| 46 | + def encontrar_blank(self): |
| 47 | + for r, row in enumerate(self.board): |
| 48 | + for c, value in enumerate(row): |
| 49 | + if value == 0: |
| 50 | + return (r, c) |
| 51 | + return None |
| 52 | + |
| 53 | + def scramble_board(self, moves=1000): |
| 54 | + n = self.board_size |
| 55 | + for _ in range(moves): |
| 56 | + r, c = self.blank_pos |
| 57 | + possiveis = [] |
| 58 | + if r > 0: |
| 59 | + possiveis.append((r - 1, c)) |
| 60 | + if r < n - 1: |
| 61 | + possiveis.append((r + 1, c)) |
| 62 | + if c > 0: |
| 63 | + possiveis.append((r, c - 1)) |
| 64 | + if c < n - 1: |
| 65 | + possiveis.append((r, c + 1)) |
| 66 | + r_swap, c_swap = random.choice(possiveis) |
| 67 | + self.board[r][c], self.board[r_swap][c_swap] = self.board[r_swap][c_swap], self.board[r][c] |
| 68 | + self.blank_pos = (r_swap, c_swap) |
| 69 | + |
| 70 | + def desenhar_menu(self): |
| 71 | + self.tela.fill(self.cor_fundo) |
| 72 | + titulo = self.fonte_menu.render("Puzzle Deslizante", True, self.cor_texto) |
| 73 | + instrucao = self.fonte_menu.render("Pressione 1: Fácil (3x3), 2: Médio (4x4), 3: Difícil (5x5)", True, self.cor_texto) |
| 74 | + self.tela.blit(titulo, (self.largura // 2 - titulo.get_width() // 2, self.altura // 3)) |
| 75 | + self.tela.blit(instrucao, (self.largura // 2 - instrucao.get_width() // 2, self.altura // 2)) |
| 76 | + pygame.display.flip() |
| 77 | + |
| 78 | + def processar_eventos_menu(self): |
| 79 | + for event in pygame.event.get(): |
| 80 | + if event.type == pygame.QUIT: |
| 81 | + self.estado = "sair" |
| 82 | + elif event.type == pygame.KEYDOWN: |
| 83 | + if event.key == pygame.K_1: |
| 84 | + self.board_size = 3 |
| 85 | + elif event.key == pygame.K_2: |
| 86 | + self.board_size = 4 |
| 87 | + elif event.key == pygame.K_3: |
| 88 | + self.board_size = 5 |
| 89 | + if self.board_size is not None: |
| 90 | + self.iniciar_jogo() |
| 91 | + self.estado = "game" |
| 92 | + |
| 93 | + def iniciar_jogo(self): |
| 94 | + self.cell_size = min(self.largura, self.altura) // self.board_size |
| 95 | + self.board = self.gerar_tabuleiro_solved(self.board_size) |
| 96 | + self.blank_pos = (self.board_size - 1, self.board_size - 1) |
| 97 | + self.score = 0 |
| 98 | + self.scramble_board(moves=1000) |
| 99 | + |
| 100 | + def desenhar_tabuleiro(self): |
| 101 | + self.tela.fill(self.cor_fundo) |
| 102 | + n = self.board_size |
| 103 | + for r in range(n): |
| 104 | + for c in range(n): |
| 105 | + val = self.board[r][c] |
| 106 | + rect = pygame.Rect(c * self.cell_size, r * self.cell_size, self.cell_size, self.cell_size) |
| 107 | + pygame.draw.rect(self.tela, self.cor_celula, rect) |
| 108 | + pygame.draw.rect(self.tela, self.cor_grid, rect, 2) |
| 109 | + if val != 0: |
| 110 | + texto = self.fonte_game.render(str(val), True, self.cor_texto) |
| 111 | + self.tela.blit(texto, (c * self.cell_size + (self.cell_size - texto.get_width()) // 2, |
| 112 | + r * self.cell_size + (self.cell_size - texto.get_height()) // 2)) |
| 113 | + |
| 114 | + def processar_eventos_game(self): |
| 115 | + for event in pygame.event.get(): |
| 116 | + if event.type == pygame.QUIT: |
| 117 | + self.estado = "sair" |
| 118 | + elif event.type == pygame.KEYDOWN: |
| 119 | + if event.key == pygame.K_ESCAPE: |
| 120 | + self.estado = "sair" |
| 121 | + elif event.type == pygame.MOUSEBUTTONDOWN: |
| 122 | + mouse_x, mouse_y = pygame.mouse.get_pos() |
| 123 | + col = mouse_x // self.cell_size |
| 124 | + row = mouse_y // self.cell_size |
| 125 | + if self.adjacente_ao_blank(row, col): |
| 126 | + self.mover_bloco(row, col) |
| 127 | + self.score += 1 |
| 128 | + |
| 129 | + def adjacent_positions(self, row, col): |
| 130 | + positions = [] |
| 131 | + if row > 0: |
| 132 | + positions.append((row - 1, col)) |
| 133 | + if row < self.board_size - 1: |
| 134 | + positions.append((row + 1, col)) |
| 135 | + if col > 0: |
| 136 | + positions.append((row, col - 1)) |
| 137 | + if col < self.board_size - 1: |
| 138 | + positions.append((row, col + 1)) |
| 139 | + return positions |
| 140 | + |
| 141 | + def adjacente_ao_blank(self, row, col): |
| 142 | + blank_r, blank_c = self.blank_pos |
| 143 | + return (row, col) in self.adjacent_positions(blank_r, blank_c) |
| 144 | + |
| 145 | + def mover_bloco(self, row, col): |
| 146 | + blank_r, blank_c = self.blank_pos |
| 147 | + self.board[blank_r][blank_c], self.board[row][col] = self.board[row][col], self.board[blank_r][blank_c] |
| 148 | + self.blank_pos = (row, col) |
| 149 | + |
| 150 | + def is_solved(self): |
| 151 | + n = self.board_size |
| 152 | + expected = 1 |
| 153 | + for r in range(n): |
| 154 | + for c in range(n): |
| 155 | + if r == n - 1 and c == n - 1: |
| 156 | + if self.board[r][c] != 0: |
| 157 | + return False |
| 158 | + else: |
| 159 | + if self.board[r][c] != expected: |
| 160 | + return False |
| 161 | + expected += 1 |
| 162 | + return True |
| 163 | + |
| 164 | + def desenhar_game_over(self): |
| 165 | + self.tela.fill(self.cor_fundo) |
| 166 | + msg = self.fonte_menu.render("Puzzle Resolvido!", True, self.cor_texto) |
| 167 | + self.tela.blit(msg, (self.largura // 2 - msg.get_width() // 2, self.altura // 2 - msg.get_height() // 2)) |
| 168 | + pygame.display.flip() |
| 169 | + pygame.time.delay(3000) |
| 170 | + |
| 171 | + def run(self): |
| 172 | + while self.estado != "sair": |
| 173 | + if self.estado == "menu": |
| 174 | + self.desenhar_menu() |
| 175 | + self.processar_eventos_menu() |
| 176 | + elif self.estado == "game": |
| 177 | + self.processar_eventos_game() |
| 178 | + self.desenhar_tabuleiro() |
| 179 | + if self.is_solved(): |
| 180 | + self.estado = "game_over" |
| 181 | + pygame.display.flip() |
| 182 | + self.relogio.tick(self.fps) |
| 183 | + elif self.estado == "game_over": |
| 184 | + self.desenhar_game_over() |
| 185 | + if self.board_size == 3: |
| 186 | + self.score = 10 |
| 187 | + elif self.board_size == 4: |
| 188 | + self.score = 20 |
| 189 | + elif self.board_size == 5: |
| 190 | + self.score = 30 |
| 191 | + self.estado = "sair" |
| 192 | + pygame.quit() |
| 193 | + return self.score |
| 194 | + |
| 195 | +if __name__ == "__main__": |
| 196 | + game = SlidingPuzzleGame() |
| 197 | + final_score = game.run() |
| 198 | + print(f"Score final: {final_score}") |
0 commit comments