From e2886499b513348b52a87fad1df325c945eecb47 Mon Sep 17 00:00:00 2001 From: ll <396463537@qq.com> Date: Sun, 15 Mar 2026 23:47:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B62048=E5=92=8C=E8=B4=AA?= =?UTF-8?q?=E5=90=83=E8=9B=87=E5=B0=8F=E6=B8=B8=E6=88=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__pycache__/game_2048.cpython-314.pyc | Bin 0 -> 11498 bytes .../__pycache__/game_snake.cpython-314.pyc | Bin 0 -> 11136 bytes game_collection/game_2048.py | 190 ++++++++++++++++++ game_collection/game_snake.py | 156 ++++++++++++++ game_collection/main.py | 109 ++++++++++ 5 files changed, 455 insertions(+) create mode 100644 game_collection/__pycache__/game_2048.cpython-314.pyc create mode 100644 game_collection/__pycache__/game_snake.cpython-314.pyc create mode 100644 game_collection/game_2048.py create mode 100644 game_collection/game_snake.py create mode 100644 game_collection/main.py diff --git a/game_collection/__pycache__/game_2048.cpython-314.pyc b/game_collection/__pycache__/game_2048.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b7533b40db9c13e8612b3452e57875f29e9d00bb GIT binary patch literal 11498 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 1024: + font = pygame.font.SysFont('Arial', 28, bold=True) + elif value >= 128: + font = pygame.font.SysFont('Arial', 32, bold=True) + else: + font = self.font_large + text = font.render(str(value), True, text_color) + text_rect = text.get_rect(center=(x + CELL_SIZE // 2, y + CELL_SIZE // 2)) + self.screen.blit(text, text_rect) + + if self.win: + self.draw_overlay('You Win!', 'Press R to restart') + elif self.game_over: + self.draw_overlay('Game Over!', 'Press R to restart') + + def draw_overlay(self, title, subtitle): + overlay = pygame.Surface((WINDOW_SIZE - MARGIN, WINDOW_SIZE - MARGIN)) + overlay.fill((255, 255, 255)) + overlay.set_alpha(180) + self.screen.blit(overlay, (MARGIN, HEADER_HEIGHT)) + + title_text = self.font_large.render(title, True, (119, 110, 101)) + title_rect = title_text.get_rect(center=(WINDOW_SIZE // 2, HEADER_HEIGHT + (WINDOW_SIZE - HEADER_HEIGHT) // 2 - 20)) + self.screen.blit(title_text, title_rect) + + sub_text = self.font_small.render(subtitle, True, (150, 150, 150)) + sub_rect = sub_text.get_rect(center=(WINDOW_SIZE // 2, HEADER_HEIGHT + (WINDOW_SIZE - HEADER_HEIGHT) // 2 + 20)) + self.screen.blit(sub_text, sub_rect) diff --git a/game_collection/game_snake.py b/game_collection/game_snake.py new file mode 100644 index 0000000..aa9e13d --- /dev/null +++ b/game_collection/game_snake.py @@ -0,0 +1,156 @@ +import pygame +import time +import numpy as np +from pygame.locals import * + +BOARDWIDTH = 48 +BOARDHEIGHT = 28 + +class Food: + def __init__(self): + self.item = (4, 5) + + def _draw(self, screen, i, j): + color = 255, 0, 255 + radius = 10 + width = 10 + position = 10 + 20 * i, 10 + 20 * j + pygame.draw.circle(screen, color, position, radius, width) + + def update(self, screen, enlarge, snack): + if enlarge: + self.item = np.random.randint(1, BOARDWIDTH - 2), np.random.randint(1, BOARDHEIGHT - 2) + while self.item in snack.item: + self.item = np.random.randint(1, BOARDWIDTH - 2), np.random.randint(1, BOARDHEIGHT - 2) + self._draw(screen, self.item[0], self.item[1]) + +class Snack: + def __init__(self): + self.item = [(3, 25), (2, 25), (1, 25), (1, 24)] + self.x = 0 + self.y = -1 + + def move(self, enlarge): + if not enlarge: + self.item.pop() + head = (self.item[0][0] + self.x, self.item[0][1] + self.y) + self.item.insert(0, head) + + def eat_food(self, food): + snack_x, snack_y = self.item[0] + food_x, food_y = food.item + if (food_x == snack_x) and (food_y == snack_y): + return 1 + else: + return 0 + + def toward(self, x, y): + if self.x * x >= 0 and self.y * y >= 0: + self.x = x + self.y = y + + def get_head(self): + return self.item[0] + + def draw(self, screen): + radius = 15 + width = 15 + color = 255, 0, 0 + position = 10 + 20 * self.item[0][0], 10 + 20 * self.item[0][1] + pygame.draw.circle(screen, color, position, radius, width) + radius = 10 + width = 10 + color = 255, 255, 0 + for i, j in self.item[1:]: + position = 10 + 20 * i, 10 + 20 * j + pygame.draw.circle(screen, color, position, radius, width) + +class GameSnake: + def __init__(self, screen): + self.screen = screen + self.font = pygame.font.SysFont('Arial', 20) + self.font_large = pygame.font.SysFont('Arial', 40) + self.reset() + + def reset(self): + self.snack = Snack() + self.food = Food() + self.score = 0 + self.is_fail = False + self.last_move_time = time.time() + self.move_delay = 0.1 + + def init_board(self): + board_width = BOARDWIDTH + board_height = BOARDHEIGHT + color = 10, 255, 255 + width = 0 + for i in range(board_width): + pos = i * 20, 0, 20, 20 + pygame.draw.rect(self.screen, color, pos, width) + pos = i * 20, (board_height - 1) * 20, 20, 20 + pygame.draw.rect(self.screen, color, pos, width) + for i in range(board_height - 1): + pos = 0, 20 + i * 20, 20, 20 + pygame.draw.rect(self.screen, color, pos, width) + pos = (board_width - 1) * 20, 20 + i * 20, 20, 20 + pygame.draw.rect(self.screen, color, pos, width) + + def game_over(self): + broad_x, broad_y = self.snack.get_head() + flag = 0 + old = len(self.snack.item) + new = len(set(self.snack.item)) + if new < old: + flag = 1 + if broad_x == 0 or broad_x == BOARDWIDTH - 1: + flag = 1 + if broad_y == 0 or broad_y == BOARDHEIGHT - 1: + flag = 1 + return flag == 1 + + def print_text(self, x, y, text, color=(255, 0, 0)): + imgText = self.font.render(text, True, color) + self.screen.blit(imgText, (x, y)) + + def handle_input(self, keys): + if keys[K_w] or keys[K_UP]: + self.snack.toward(0, -1) + elif keys[K_s] or keys[K_DOWN]: + self.snack.toward(0, 1) + elif keys[K_a] or keys[K_LEFT]: + self.snack.toward(-1, 0) + elif keys[K_d] or keys[K_RIGHT]: + self.snack.toward(1, 0) + elif keys[K_r]: + self.reset() + + def update(self): + current_time = time.time() + if current_time - self.last_move_time >= self.move_delay: + self.last_move_time = current_time + if not self.is_fail: + enlarge = self.snack.eat_food(self.food) + if enlarge: + self.score += 100 + self.food.update(self.screen, enlarge, self.snack) + self.snack.move(enlarge) + self.is_fail = self.game_over() + + def draw(self): + self.screen.fill((0, 0, 100)) + self.init_board() + + text = f"Score: {self.score} | WASD/Arrows: Move | R: Reset | ESC: Switch Game" + self.print_text(0, 0, text) + + if self.is_fail: + game_over_text = self.font_large.render("GAME OVER", True, (255, 255, 255)) + text_rect = game_over_text.get_rect(center=(BOARDWIDTH * 10, BOARDHEIGHT * 10)) + self.screen.blit(game_over_text, text_rect) + hint_text = self.font.render("Press R to restart", True, (200, 200, 200)) + hint_rect = hint_text.get_rect(center=(BOARDWIDTH * 10, BOARDHEIGHT * 10 + 40)) + self.screen.blit(hint_text, hint_rect) + else: + self.food.update(self.screen, False, self.snack) + self.snack.draw(self.screen) diff --git a/game_collection/main.py b/game_collection/main.py new file mode 100644 index 0000000..19b2ee5 --- /dev/null +++ b/game_collection/main.py @@ -0,0 +1,109 @@ +import pygame +import sys +from pygame.locals import * + +from game_2048 import Game2048 +from game_snake import GameSnake, BOARDWIDTH, BOARDHEIGHT + +SCREEN_WIDTH_2048 = 440 +SCREEN_HEIGHT_2048 = 520 + +SCREEN_WIDTH_SNAKE = BOARDWIDTH * 20 +SCREEN_HEIGHT_SNAKE = BOARDHEIGHT * 20 + +class GameCollection: + def __init__(self): + pygame.init() + self.current_game = 'menu' + self.screen = None + self.game_2048 = None + self.game_snake = None + self.font_large = pygame.font.SysFont('Arial', 48, bold=True) + self.font_medium = pygame.font.SysFont('Arial', 32) + self.font_small = pygame.font.SysFont('Arial', 24) + + def create_screen(self, width, height, title): + screen = pygame.display.set_mode((width, height)) + pygame.display.set_caption(title) + return screen + + def draw_menu(self): + self.screen.fill((250, 248, 239)) + + title = self.font_large.render('Game Collection', True, (119, 110, 101)) + title_rect = title.get_rect(center=(SCREEN_WIDTH_2048 // 2, 100)) + self.screen.blit(title, title_rect) + + games = [ + ('1. 2048', 'Press 1 to play'), + ('2. Snake', 'Press 2 to play'), + ] + + y_pos = 200 + for game_name, hint in games: + name_text = self.font_medium.render(game_name, True, (119, 110, 101)) + name_rect = name_text.get_rect(center=(SCREEN_WIDTH_2048 // 2, y_pos)) + self.screen.blit(name_text, name_rect) + + hint_text = self.font_small.render(hint, True, (150, 150, 150)) + hint_rect = hint_text.get_rect(center=(SCREEN_WIDTH_2048 // 2, y_pos + 35)) + self.screen.blit(hint_text, hint_rect) + + y_pos += 100 + + exit_text = self.font_small.render('Press ESC to exit', True, (150, 150, 150)) + exit_rect = exit_text.get_rect(center=(SCREEN_WIDTH_2048 // 2, y_pos + 50)) + self.screen.blit(exit_text, exit_rect) + + def run(self): + clock = pygame.time.Clock() + + while True: + for event in pygame.event.get(): + if event.type == QUIT: + pygame.quit() + sys.exit() + + if event.type == KEYDOWN: + if event.key == K_ESCAPE: + if self.current_game == 'menu': + pygame.quit() + sys.exit() + else: + self.current_game = 'menu' + self.screen = self.create_screen(SCREEN_WIDTH_2048, SCREEN_HEIGHT_2048, 'Game Collection') + + elif self.current_game == 'menu': + if event.key == K_1: + self.current_game = '2048' + self.screen = self.create_screen(SCREEN_WIDTH_2048, SCREEN_HEIGHT_2048, '2048') + self.game_2048 = Game2048(self.screen) + elif event.key == K_2: + self.current_game = 'snake' + self.screen = self.create_screen(SCREEN_WIDTH_SNAKE, SCREEN_HEIGHT_SNAKE, 'Snake') + self.game_snake = GameSnake(self.screen) + + elif self.current_game == '2048': + self.game_2048.handle_input(event.key) + + elif self.current_game == 'snake': + if event.key == K_r: + self.game_snake.reset() + + if self.current_game == 'menu': + self.screen = self.screen or self.create_screen(SCREEN_WIDTH_2048, SCREEN_HEIGHT_2048, 'Game Collection') + self.draw_menu() + elif self.current_game == '2048': + self.game_2048.draw() + elif self.current_game == 'snake': + keys = pygame.key.get_pressed() + self.game_snake.handle_input(keys) + self.game_snake.update() + self.game_snake.draw() + + pygame.display.update() + clock.tick(60) + +if __name__ == '__main__': + collection = GameCollection() + collection.run()