Загрузка данных


import random
import pygame
import sys

# Инициализация Pygame
pygame.init()

# Константы
FPS = 10
WINDOW_WIDTH = 600
WINDOW_HEIGHT = 600
CELL_SIZE = 10

# Цвета (RGB)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
DARK_GREEN = (0, 150, 0)

class Snake():
    def __init__(self, snake_color):
        # Важные переменные - позиция головы змеи и его тела
        self.snake_head_pos = [100, 50]  # [x, y]
        # начальное тело змеи состоит из трех сегментов
        # голова змеи - первый элемент, хвост - последний
        self.snake_body = [[100, 50], [90, 50], [80, 50]]
        self.snake_color = snake_color
        # направления движения змеи, изначально зададимся вправо
        self.direction = "RIGHT"
        # куда будет меняться направление движения змеи при нажатии соответствующих клавиш
        self.change_to = self.direction

    def validate_direction_and_change(self):
        """Изменим направление движения змеи только в том случае,
        если оно не прямо противоположно текущему"""
        if self.change_to == "RIGHT" and not self.direction == "LEFT":
            self.direction = self.change_to
        elif self.change_to == "LEFT" and not self.direction == "RIGHT":
            self.direction = self.change_to
        elif self.change_to == "UP" and not self.direction == "DOWN":
            self.direction = self.change_to
        elif self.change_to == "DOWN" and not self.direction == "UP":
            self.direction = self.change_to

    def change_head_position(self):
        """Изменим положение головы змеи"""
        if self.direction == "RIGHT":
            self.snake_head_pos[0] += CELL_SIZE
        elif self.direction == "LEFT":
            self.snake_head_pos[0] -= CELL_SIZE
        elif self.direction == "UP":
            self.snake_head_pos[1] -= CELL_SIZE  # Исправлено: было [0] -= 10
        elif self.direction == "DOWN":
            self.snake_head_pos[1] += CELL_SIZE

    def snake_body_mechanism(self, score, food_pos, screen_width, screen_height):
        # Вставляем новую голову (копируем, чтобы не было ссылки)
        self.snake_body.insert(0, list(self.snake_head_pos))
        
        # если съели еду
        if (self.snake_head_pos[0] == food_pos[0] and
            self.snake_head_pos[1] == food_pos[1]):
            # задаем новое положение еды случайным образом
            food_pos = [random.randint(0, (screen_width - CELL_SIZE) // CELL_SIZE) * CELL_SIZE,
                        random.randint(0, (screen_height - CELL_SIZE) // CELL_SIZE) * CELL_SIZE]
            score += 1
        else:
            # если не нашли еду, то убираем последний сегмент
            self.snake_body.pop()
        return score, food_pos

    def draw_snake(self, play_surface, surface_color):
        """Отображаем все сегменты змеи"""
        for segment in self.snake_body:
            pygame.draw.rect(play_surface, self.snake_color,
                           (segment[0], segment[1], CELL_SIZE, CELL_SIZE))
            # Добавляем небольшую обводку для красоты
            pygame.draw.rect(play_surface, surface_color,
                           (segment[0], segment[1], CELL_SIZE, CELL_SIZE), 1)

    def check_collision(self, screen_width, screen_height):
        # Столкновение со стенами
        if (self.snake_head_pos[0] < 0 or
            self.snake_head_pos[0] >= screen_width or
            self.snake_head_pos[1] < 0 or
            self.snake_head_pos[1] >= screen_height):
            return True
        
        # Столкновение с самим собой (проверяем, не врезалась ли голова в тело)
        for segment in self.snake_body[1:]:
            if self.snake_head_pos[0] == segment[0] and self.snake_head_pos[1] == segment[1]:
                return True
        return False

    def reset(self):
        """Сброс змеи до начального состояния"""
        self.snake_head_pos = [100, 50]
        self.snake_body = [[100, 50], [90, 50], [80, 50]]
        self.direction = "RIGHT"
        self.change_to = self.direction


def show_game_over(screen, score):
    """Отображение экрана Game Over"""
    font = pygame.font.Font(None, 72)
    font_small = pygame.font.Font(None, 36)
    
    game_over_text = font.render("GAME OVER", True, RED)
    score_text = font_small.render(f"Счёт: {score}", True, WHITE)
    restart_text = font_small.render("Нажмите SPACE чтобы сыграть снова или ESC для выхода", True, WHITE)
    
    screen.fill(BLACK)
    screen.blit(game_over_text, (WINDOW_WIDTH // 2 - game_over_text.get_width() // 2,
                                 WINDOW_HEIGHT // 2 - 100))
    screen.blit(score_text, (WINDOW_WIDTH // 2 - score_text.get_width() // 2,
                             WINDOW_HEIGHT // 2 - 20))
    screen.blit(restart_text, (WINDOW_WIDTH // 2 - restart_text.get_width() // 2,
                               WINDOW_HEIGHT // 2 + 40))
    pygame.display.update()
    
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    return True  # Перезапуск
                if event.key == pygame.K_ESCAPE:
                    return False  # Выход


def main():
    screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
    pygame.display.set_caption("Змейка")
    clock = pygame.time.Clock()
    
    # Основной игровой цикл (с возможностью перезапуска)
    running = True
    while running:
        # Инициализация игры
        snake = Snake(DARK_GREEN)
        
        # Позиция еды
        food_pos = [random.randint(0, (WINDOW_WIDTH - CELL_SIZE) // CELL_SIZE) * CELL_SIZE,
                    random.randint(0, (WINDOW_HEIGHT - CELL_SIZE) // CELL_SIZE) * CELL_SIZE]
        score = 0
        
        game_loop = True
        while game_loop:
            # Обработка событий
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_RIGHT or event.key == ord('d'):
                        snake.change_to = "RIGHT"
                    elif event.key == pygame.K_LEFT or event.key == ord('a'):
                        snake.change_to = "LEFT"
                    elif event.key == pygame.K_UP or event.key == ord('w'):
                        snake.change_to = "UP"
                    elif event.key == pygame.K_DOWN or event.key == ord('s'):
                        snake.change_to = "DOWN"
                    elif event.key == pygame.K_ESCAPE:
                        game_loop = False
                        running = False
            
            # Проверка и применение направления
            snake.validate_direction_and_change()
            snake.change_head_position()
            
            # Проверка столкновений
            if snake.check_collision(WINDOW_WIDTH, WINDOW_HEIGHT):
                game_loop = False
                continue
            
            # Обновление тела змеи и проверка поедания еды
            score, food_pos = snake.snake_body_mechanism(score, food_pos, WINDOW_WIDTH, WINDOW_HEIGHT)
            
            # Отрисовка
            screen.fill(BLACK)
            
            # Рисуем еду (красный квадрат)
            pygame.draw.rect(screen, RED,
                           (food_pos[0], food_pos[1], CELL_SIZE, CELL_SIZE))
            
            # Рисуем змею
            snake.draw_snake(screen, WHITE)
            
            # Отображение счёта
            font = pygame.font.Font(None, 36)
            score_text = font.render(f"Счёт: {score}", True, WHITE)
            screen.blit(score_text, (10, 10))
            
            pygame.display.update()
            clock.tick(FPS)
        
        # Если игра закончена, показываем экран Game Over
        if not running:
            break
        
        # Показываем Game Over и спрашиваем о перезапуске
        if not show_game_over(screen, score):
            running = False
    
    pygame.quit()
    sys.exit()


if __name__ == "__main__":
    main()