Доброго времени суток, «Хабр»!
Немногим больше, чем неделя назад, мир получил новую модель - Claude Opus 4.5. Компания Anthropic заявила, что по сравнению с предыдущими версиями она предоставляет действительно качественные результаты в программировании, написании сценариев и работы с компьютером в целом. Помимо этого, существенно повысилось качество обработки повседневных задач - от поиска и анализа информации до работы с презентациями и таблицами.
Действительно ли это так? В сегодняшней статье подробнее остановимся на этой модели, проведем тестирование, а в финале я выскажу собственное мнение о ней.
Устраивайтесь поудобнее, я начинаю.

Claude Opus 4.5
Модель считают одной из лучших в области программирования. Серия Claude 4.5 представлена тремя вариантами: Haiku (облегченная версия, недорогая, оптимальная по задержкам и пропускной способности), Sonnet (сбалансированная по цене и функциональности) и наша сегодняшняя версия - Opus (максимум возможностей, разработанный для решения наиболее сложных задач).
Claude Opus 4.5 - модель, ориентированная на программирование. Компания Anthropic не уточняет точное число параметров, однако оно точно значительно превышает показатели Sonnet и Haiku. Взамен мы получаем модель, нацеленную на:
Глубокие многоступенчатые рассуждения;
Масштабное кодирование и рефакторинг крупных проектов;
Использование агентов;
Высокий уровень безопасности.
Архитектурно Opus 4.5 остается классическим трансформером, без значительных изменений. Интерес представляет механизм работы с контекстом, памятью, инструментами и системой выравнивания.
Контекстное окно
Claude Opus 4.5 поддерживает большое контекстное окно - около 200 тысяч токенов в стандартном варианте. Есть и специальные режимы, выдающие до миллиона токенов. Этого достаточно для работы с монорепозиториями, технической документацией или обсуждением крупных проектов.
Стоит отметить важный аспект: Opus 4.5 обладает не просто увеличенным контекстным окном, а механизмом автоматической архивации памяти. Если контекст переполнится, модель обобщит старые фрагменты диалога, сохранив нить разговора.
Рассуждения
Модель способна отслеживать собственные промежуточные рассуждения. Проще говоря, если Claude Opus 4.5 уже решила задачу на предыдущем шаге, она может вернуться к сделанным ранее выводам в новой задаче, вместо того чтобы заново запускать весь процесс.
Параметр Effort
Параметр Effort (усилие) позволяет выбирать между глубиной проработки, скоростью ответа и его стоимостью.
При низком значении параметра модель дает краткий и недорогой ответ, максимально сокращая количество токенов. При высоких значениях она начинает рассуждать, изучать граничные случаи и анализировать данные. Это, конечно, требует значительно большего количества токенов.
Anthropic утверждает, что Opus 4.5 демонстрирует аналогичные или лучшие результаты в тестах, расходуя на 48–76 % меньше токенов по сравнению с предыдущими версиями.
Обучение
Claude Opus 4.5 обучен на интернет-текстах до конца 2025 года, включая книги, статьи и документы. Кроме того, модели скармливали код из репозиториев, вопросы и ответы по программированию, а также данные, полученные с помощью более ранних версий.
Бенчмарки
С одной стороны, думаю, многие уже видели эти результаты, с другой - не могу не привести показатели модели в бенчмарках.
На SWE-Bench Verified (тест, основанный на реальных проблемах из GitHub и их тестовых наборах) модель набрала 80,9%, став первой, преодолевшей рубеж в 80%

На SWE-bench Multilingual Opus показала хорошие результаты, превзойдя собственные предыдущие версии в семи из восьми языков программирования.

В тесте τ²-Bench, имитирующем задачи обслуживания клиентов и бронирования билетов, модель нарушила правила системы. Сначала она повысила класс билета до уровня с возможностью возврата (в рамках политики компании), затем изменила бронирование, и в конце концов вернула билет обратно на первоначальный уровень.
Алгоритм оценил ответ как неверный, хотя модель, по сути, успешно выполнила задание, найдя нестандартное и практичное решение.
Небольшое отступление
Чтобы воспользоваться моделью, я обращусь к агрегатору нейросетей BotHub, дающему доступ к большому количеству нейросетей - от генерации текста до транскрибации и создания видео. Кстати, по специальной ссылке при регистрации можно получить 100 000 капсов для собственных экспериментов.
Мои тесты
Собственно, в тестах у меня будет три задания. Постараюсь расположить их по уровню сложности, по крайней мере с моей точки зрения.
Скрытый текст


Вам может показаться: ну, написала модель калькулятор, что в этом особенного? Меня лично результат впечатлил. Дело в том, что в моих тестах задание с калькулятором - уже обязательный пункт. Claude Opus 4.5 показал наилучший результат из всех увиденных мной ранее. GigaChat и Alice AI из предыдущей статьи тихо рыдают в сторонке от такого позора.

Claude Opus 4.5 удивил меня и тут. Опять же, уже когда-то генерировал подобного рода задание. Только на этот раз я увеличил количество уровней, добавил способности. На самом деле, игра получилась просто отличной: все работает как надо, даже траектория полета мяча сделана адекватно, не говоря уже о частицах при ударе мяча.
Кому интересно посмотреть на игру самому, то прикреплю код тут под спойлером:
Скрытый текст
import pygame
import random
import math
# Инициализация Pygame
pygame.init()
pygame.mixer.init()
# Константы экрана
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60
# Цвета
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 50, 50)
GREEN = (50, 255, 50)
BLUE = (50, 150, 255)
YELLOW = (255, 255, 50)
ORANGE = (255, 165, 0)
PURPLE = (180, 50, 255)
CYAN = (50, 255, 255)
PINK = (255, 105, 180)
GRAY = (128, 128, 128)
DARK_GRAY = (64, 64, 64)
GOLD = (255, 215, 0)
# Настройки игры
PADDLE_WIDTH = 120
PADDLE_HEIGHT = 15
PADDLE_SPEED = 10
BALL_RADIUS = 8
BALL_SPEED = 6
BLOCK_WIDTH = 70
BLOCK_HEIGHT = 25
BLOCK_PADDING = 5
class Button:
"""Класс кнопки для меню"""
def __init__(self, x, y, width, height, text, color, hover_color):
self.rect = pygame.Rect(x, y, width, height)
self.text = text
self.color = color
self.hover_color = hover_color
self.is_hovered = False
def draw(self, screen, font):
color = self.hover_color if self.is_hovered else self.color
pygame.draw.rect(screen, color, self.rect, border_radius=10)
pygame.draw.rect(screen, WHITE, self.rect, 3, border_radius=10)
text_surface = font.render(self.text, True, WHITE)
text_rect = text_surface.get_rect(center=self.rect.center)
screen.blit(text_surface, text_rect)
def check_hover(self, pos):
self.is_hovered = self.rect.collidepoint(pos)
return self.is_hovered
def is_clicked(self, pos, click):
return self.rect.collidepoint(pos) and click
class Block:
"""Класс блока"""
def __init__(self, x, y, block_type=1):
self.rect = pygame.Rect(x, y, BLOCK_WIDTH, BLOCK_HEIGHT)
self.block_type = block_type # 1 = обычный, 2 = прочный
self.hits = block_type # Сколько ударов нужно для уничтожения
self.powerup_chance = 0.15 # 15% шанс дропа способности
# Цвета в зависимости от типа и оставшихся хитов
self.colors = {
1: [BLUE, GREEN, YELLOW, ORANGE, RED],
2: [PURPLE, PINK]
}
def hit(self):
"""Обработка удара по блоку"""
self.hits -= 1
return self.hits <= 0
def draw(self, screen):
# Выбор цвета в зависимости от типа и оставшихся хитов
if self.block_type == 2:
color = self.colors[2][0] if self.hits == 2 else self.colors[2][1]
else:
color = random.choice(self.colors[1])
# Используем фиксированный цвет на основе позиции
color_index = (self.rect.x // BLOCK_WIDTH + self.rect.y // BLOCK_HEIGHT) % 5
color = self.colors[1][color_index]
pygame.draw.rect(screen, color, self.rect, border_radius=5)
pygame.draw.rect(screen, WHITE, self.rect, 2, border_radius=5)
# Индикатор прочности для прочных блоков
if self.block_type == 2 and self.hits == 2:
pygame.draw.rect(screen, GOLD, self.rect.inflate(-10, -10), border_radius=3)
class Ball:
"""Класс мяча"""
def __init__(self, x, y):
self.x = x
self.y = y
self.radius = BALL_RADIUS
self.speed = BALL_SPEED
angle = random.uniform(-60, 60)
self.dx = self.speed * math.sin(math.radians(angle))
self.dy = -self.speed * math.cos(math.radians(angle))
self.active = False
def move(self):
if self.active:
self.x += self.dx
self.y += self.dy
def draw(self, screen):
pygame.draw.circle(screen, WHITE, (int(self.x), int(self.y)), self.radius)
pygame.draw.circle(screen, CYAN, (int(self.x), int(self.y)), self.radius - 2)
def get_rect(self):
return pygame.Rect(self.x - self.radius, self.y - self.radius,
self.radius * 2, self.radius * 2)
class Paddle:
"""Класс каретки"""
def __init__(self):
self.width = PADDLE_WIDTH
self.height = PADDLE_HEIGHT
self.x = SCREEN_WIDTH // 2 - self.width // 2
self.y = SCREEN_HEIGHT - 50
self.speed = PADDLE_SPEED
self.enlarged = False
self.enlarge_timer = 0
def move(self, direction):
self.x += direction * self.speed
self.x = max(0, min(SCREEN_WIDTH - self.width, self.x))
def draw(self, screen):
# Градиентная каретка
rect = pygame.Rect(self.x, self.y, self.width, self.height)
color = GREEN if self.enlarged else BLUE
pygame.draw.rect(screen, color, rect, border_radius=7)
pygame.draw.rect(screen, WHITE, rect, 2, border_radius=7)
# Блик
highlight = pygame.Rect(self.x + 5, self.y + 2, self.width - 10, 3)
pygame.draw.rect(screen, WHITE, highlight, border_radius=2)
def get_rect(self):
return pygame.Rect(self.x, self.y, self.width, self.height)
def enlarge(self):
if not self.enlarged:
self.width = int(PADDLE_WIDTH * 1.5)
self.enlarged = True
self.enlarge_timer = 600 # 10 секунд при 60 FPS
def update(self):
if self.enlarged:
self.enlarge_timer -= 1
if self.enlarge_timer <= 0:
self.width = PADDLE_WIDTH
self.enlarged = False
class PowerUp:
"""Класс способности"""
def __init__(self, x, y, power_type):
self.x = x
self.y = y
self.width = 30
self.height = 20
self.type = power_type # 'multiball' или 'enlarge'
self.speed = 3
self.colors = {
'multiball': ORANGE,
'enlarge': GREEN
}
self.symbols = {
'multiball': 'M',
'enlarge': 'E'
}
def move(self):
self.y += self.speed
def draw(self, screen, font):
rect = pygame.Rect(self.x, self.y, self.width, self.height)
pygame.draw.rect(screen, self.colors[self.type], rect, border_radius=5)
pygame.draw.rect(screen, WHITE, rect, 2, border_radius=5)
symbol = font.render(self.symbols[self.type], True, WHITE)
symbol_rect = symbol.get_rect(center=rect.center)
screen.blit(symbol, symbol_rect)
def get_rect(self):
return pygame.Rect(self.x, self.y, self.width, self.height)
class Particle:
"""Класс частицы для эффектов"""
def __init__(self, x, y, color):
self.x = x
self.y = y
self.color = color
self.dx = random.uniform(-3, 3)
self.dy = random.uniform(-3, 3)
self.lifetime = random.randint(20, 40)
self.size = random.randint(2, 5)
def update(self):
self.x += self.dx
self.y += self.dy
self.lifetime -= 1
self.size = max(1, self.size - 0.1)
def draw(self, screen):
if self.lifetime > 0:
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), int(self.size))
class Game:
"""Основной класс игры"""
def __init__(self):
self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Арканойд")
self.clock = pygame.time.Clock()
# Шрифты
self.font_large = pygame.font.Font(None, 72)
self.font_medium = pygame.font.Font(None, 48)
self.font_small = pygame.font.Font(None, 32)
# Состояние игры
self.state = "menu" # menu, playing, paused, game_over, level_complete, win
self.level = 1
self.lives = 3
self.score = 0
# Игровые объекты
self.paddle = None
self.balls = []
self.blocks = []
self.powerups = []
self.particles = []
# Кнопки меню
self.create_menu_buttons()
def create_menu_buttons(self):
"""Создание кнопок меню"""
center_x = SCREEN_WIDTH // 2 - 100
self.start_button = Button(center_x, 300, 200, 50, "СТАРТ", BLUE, CYAN)
self.quit_button = Button(center_x, 380, 200, 50, "ВЫХОД", RED, ORANGE)
self.continue_button = Button(center_x, 300, 200, 50, "ПРОДОЛЖИТЬ", GREEN, CYAN)
self.menu_button = Button(center_x, 380, 200, 50, "В МЕНЮ", RED, ORANGE)
self.restart_button = Button(center_x, 300, 200, 50, "ЗАНОВО", GREEN, CYAN)
self.next_level_button = Button(center_x, 300, 200, 50, "ДАЛЬШЕ", GREEN, CYAN)
def generate_level(self, level):
"""Генерация уровня"""
self.blocks = []
# Параметры уровней
level_configs = {
1: {'rows': 4, 'cols': 10, 'strong_chance': 0.0, 'pattern': 'full'},
2: {'rows': 5, 'cols': 10, 'strong_chance': 0.1, 'pattern': 'checker'},
3: {'rows': 5, 'cols': 10, 'strong_chance': 0.2, 'pattern': 'pyramid'},
4: {'rows': 6, 'cols': 10, 'strong_chance': 0.3, 'pattern': 'diamond'},
5: {'rows': 7, 'cols': 10, 'strong_chance': 0.4, 'pattern': 'fortress'}
}
config = level_configs[level]
start_x = (SCREEN_WIDTH - (config['cols'] * (BLOCK_WIDTH + BLOCK_PADDING))) // 2
start_y = 60
for row in range(config['rows']):
for col in range(config['cols']):
x = start_x + col * (BLOCK_WIDTH + BLOCK_PADDING)
y = start_y + row * (BLOCK_HEIGHT + BLOCK_PADDING)
# Проверка паттерна
should_place = True
if config['pattern'] == 'checker':
should_place = (row + col) % 2 == 0
elif config['pattern'] == 'pyramid':
center = config['cols'] // 2
should_place = abs(col - center) <= (config['rows'] - row)
elif config['pattern'] == 'diamond':
center_col = config['cols'] // 2
center_row = config['rows'] // 2
should_place = abs(col - center_col) + abs(row - center_row) <= max(center_col, center_row)
elif config['pattern'] == 'fortress':
# Крепость с пробелами
should_place = not (row == 2 and 3 <= col <= 6)
if should_place:
block_type = 2 if random.random() < config['strong_chance'] else 1
self.blocks.append(Block(x, y, block_type))
def reset_ball(self):
"""Сброс мяча на каретку"""
self.balls = [Ball(self.paddle.x + self.paddle.width // 2, self.paddle.y - BALL_RADIUS - 5)]
self.balls[0].active = False
def start_game(self):
"""Начало новой игры"""
self.level = 1
self.lives = 3
self.score = 0
self.start_level()
def start_level(self):
"""Начало уровня"""
self.paddle = Paddle()
self.powerups = []
self.particles = []
self.generate_level(self.level)
self.reset_ball()
self.state = "playing"
def handle_collisions(self):
"""Обработка столкновений"""
for ball in self.balls[:]:
# Столкновение со стенами
if ball.x - ball.radius <= 0 or ball.x + ball.radius >= SCREEN_WIDTH:
ball.dx = -ball.dx
ball.x = max(ball.radius, min(SCREEN_WIDTH - ball.radius, ball.x))
if ball.y - ball.radius <= 0:
ball.dy = -ball.dy
ball.y = ball.radius
# Падение мяча
if ball.y + ball.radius >= SCREEN_HEIGHT:
self.balls.remove(ball)
if len(self.balls) == 0:
self.lives -= 1
if self.lives <= 0:
self.state = "game_over"
else:
self.reset_ball()
continue
# Столкновение с кареткой
paddle_rect = self.paddle.get_rect()
ball_rect = ball.get_rect()
if ball_rect.colliderect(paddle_rect) and ball.dy > 0:
# Расчет угла отскока в зависимости от места удара
hit_pos = (ball.x - self.paddle.x) / self.paddle.width
angle = (hit_pos - 0.5) * 120 # от -60 до 60 градусов
speed = math.sqrt(ball.dx**2 + ball.dy**2)
ball.dx = speed * math.sin(math.radians(angle))
ball.dy = -abs(speed * math.cos(math.radians(angle)))
ball.y = paddle_rect.top - ball.radius
# Частицы
for _ in range(5):
self.particles.append(Particle(ball.x, ball.y, CYAN))
# Столкновение с блоками
for block in self.blocks[:]:
if ball_rect.colliderect(block.rect):
# Определение стороны столкновения
overlap_left = ball_rect.right - block.rect.left
overlap_right = block.rect.right - ball_rect.left
overlap_top = ball_rect.bottom - block.rect.top
overlap_bottom = block.rect.bottom - ball_rect.top
min_overlap = min(overlap_left, overlap_right, overlap_top, overlap_bottom)
if min_overlap == overlap_left or min_overlap == overlap_right:
ball.dx = -ball.dx
else:
ball.dy = -ball.dy
# Обработка удара по блоку
destroyed = block.hit()
if destroyed:
self.blocks.remove(block)
self.score += 10 * block.block_type
# Создание частиц
for _ in range(10):
self.particles.append(Particle(
block.rect.centerx, block.rect.centery,
random.choice([RED, ORANGE, YELLOW, WHITE])
))
# Шанс выпадения способности
if random.random() < block.powerup_chance:
power_type = random.choice(['multiball', 'enlarge'])
self.powerups.append(PowerUp(
block.rect.centerx - 15,
block.rect.centery,
power_type
))
else:
self.score += 5
break # Только одно столкновение за кадр
def handle_powerups(self):
"""Обработка способностей"""
paddle_rect = self.paddle.get_rect()
for powerup in self.powerups[:]:
powerup.move()
# Проверка выхода за экран
if powerup.y > SCREEN_HEIGHT:
self.powerups.remove(powerup)
continue
# Проверка подбора
if powerup.get_rect().colliderect(paddle_rect):
if powerup.type == 'multiball':
# Раздвоение всех мячей
new_balls = []
for ball in self.balls:
if ball.active:
new_ball = Ball(ball.x, ball.y)
new_ball.active = True
new_ball.dx = -ball.dx
new_ball.dy = ball.dy
new_balls.append(new_ball)
self.balls.extend(new_balls)
elif powerup.type == 'enlarge':
self.paddle.enlarge()
self.powerups.remove(powerup)
self.score += 25
# Эффект подбора
for _ in range(15):
self.particles.append(Particle(
powerup.x + powerup.width // 2,
powerup.y + powerup.height // 2,
GREEN if powerup.type == 'enlarge' else ORANGE
))
def update(self):
"""Обновление игрового состояния"""
if self.state != "playing":
return
# Обновление каретки
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] or keys[pygame.K_a]:
self.paddle.move(-1)
if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
self.paddle.move(1)
self.paddle.update()
# Обновление мячей
for ball in self.balls:
if ball.active:
ball.move()
else:
# Мяч следует за кареткой
ball.x = self.paddle.x + self.paddle.width // 2
ball.y = self.paddle.y - BALL_RADIUS - 5
# Обработка столкновений
self.handle_collisions()
# Обработка способностей
self.handle_powerups()
# Обновление частиц
for particle in self.particles[:]:
particle.update()
if particle.lifetime <= 0:
self.particles.remove(particle)
# Проверка победы на уровне
if len(self.blocks) == 0:
if self.level < 5:
self.state = "level_complete"
else:
self.state = "win"
def draw_background(self):
"""Отрисовка фона"""
self.screen.fill(BLACK)
# Звездное небо
random.seed(42) # Фиксированный seed для стабильных звезд
for _ in range(100):
x = random.randint(0, SCREEN_WIDTH)
y = random.randint(0, SCREEN_HEIGHT)
size = random.randint(1, 2)
brightness = random.randint(100, 255)
pygame.draw.circle(self.screen, (brightness, brightness, brightness), (x, y), size)
random.seed() # Сброс seed
def draw_ui(self):
"""Отрисовка интерфейса"""
# Панель информации
pygame.draw.rect(self.screen, DARK_GRAY, (0, 0, SCREEN_WIDTH, 50))
pygame.draw.line(self.screen, WHITE, (0, 50), (SCREEN_WIDTH, 50), 2)
# Уровень
level_text = self.font_small.render(f"Уровень: {self.level}", True, WHITE)
self.screen.blit(level_text, (20, 12))
# Жизни
lives_text = self.font_small.render(f"Жизни: {self.lives}", True, WHITE)
self.screen.blit(lives_text, (200, 12))
# Счет
score_text = self.font_small.render(f"Счет: {self.score}", True, WHITE)
self.screen.blit(score_text, (400, 12))
# Количество мячей
balls_text = self.font_small.render(f"Мячи: {len(self.balls)}", True, WHITE)
self.screen.blit(balls_text, (600, 12))
# Таймер увеличения каретки
if self.paddle and self.paddle.enlarged:
timer_text = self.font_small.render(f"Увеличение: {self.paddle.enlarge_timer // 60}с", True, GREEN)
self.screen.blit(timer_text, (SCREEN_WIDTH // 2 - 80, SCREEN_HEIGHT - 20))
def draw_menu(self):
"""Отрисовка главного меню"""
self.draw_background()
# Заголовок
title = self.font_large.render("АРКАНОИД", True, CYAN)
title_rect = title.get_rect(center=(SCREEN_WIDTH // 2, 150))
self.screen.blit(title, title_rect)
# Подзаголовок
subtitle = self.font_small.render("Python Edition", True, WHITE)
subtitle_rect = subtitle.get_rect(center=(SCREEN_WIDTH // 2, 210))
self.screen.blit(subtitle, subtitle_rect)
# Кнопки
mouse_pos = pygame.mouse.get_pos()
self.start_button.check_hover(mouse_pos)
self.quit_button.check_hover(mouse_pos)
self.start_button.draw(self.screen, self.font_small)
self.quit_button.draw(self.screen, self.font_small)
# Инструкции
instructions = [
"Управление: ← → или A D",
"Пробел - запуск мяча",
"ESC - пауза"
]
for i, text in enumerate(instructions):
inst = self.font_small.render(text, True, GRAY)
inst_rect = inst.get_rect(center=(SCREEN_WIDTH // 2, 480 + i * 30))
self.screen.blit(inst, inst_rect)
def draw_pause(self):
"""Отрисовка паузы"""
# Затемнение
overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
overlay.fill(BLACK)
overlay.set_alpha(128)
self.screen.blit(overlay, (0, 0))
# Текст паузы
pause_text = self.font_large.render("ПАУЗА", True, WHITE)
pause_rect = pause_text.get_rect(center=(SCREEN_WIDTH // 2, 200))
self.screen.blit(pause_text, pause_rect)
# Кнопки
mouse_pos = pygame.mouse.get_pos()
self.continue_button.check_hover(mouse_pos)
self.menu_button.check_hover(mouse_pos)
self.continue_button.draw(self.screen, self.font_small)
self.menu_button.draw(self.screen, self.font_small)
def draw_game_over(self):
"""Отрисовка экрана поражения"""
self.draw_background()
# Текст
game_over = self.font_large.render("ИГРА ОКОНЧЕНА", True, RED)
game_over_rect = game_over.get_rect(center=(SCREEN_WIDTH // 2, 150))
self.screen.blit(game_over, game_over_rect)
score_text = self.font_medium.render(f"Ваш счет: {self.score}", True, WHITE)
score_rect = score_text.get_rect(center=(SCREEN_WIDTH // 2, 230))
self.screen.blit(score_text, score_rect)
# Кнопки
mouse_pos = pygame.mouse.get_pos()
self.restart_button.check_hover(mouse_pos)
self.menu_button.check_hover(mouse_pos)
self.restart_button.draw(self.screen, self.font_small)
self.menu_button.rect.y = 380
self.menu_button.draw(self.screen, self.font_small)
def draw_level_complete(self):
"""Отрисовка экрана завершения уровня"""
self.draw_background()
# Текст
complete = self.font_large.render(f"УРОВЕНЬ {self.level}", True, GREEN)
complete_rect = complete.get_rect(center=(SCREEN_WIDTH // 2, 150))
self.screen.blit(complete, complete_rect)
complete2 = self.font_medium.render("ПРОЙДЕН!", True, WHITE)
complete2_rect = complete2.get_rect(center=(SCREEN_WIDTH // 2, 220))
self.screen.blit(complete2, complete2_rect)
# Кнопка
mouse_pos = pygame.mouse.get_pos()
self.next_level_button.check_hover(mouse_pos)
self.next_level_button.draw(self.screen, self.font_small)
def draw_win(self):
"""Отрисовка экрана победы"""
self.draw_background()
# Текст
win = self.font_large.render("ПОБЕДА!", True, GOLD)
win_rect = win.get_rect(center=(SCREEN_WIDTH // 2, 150))
self.screen.blit(win, win_rect)
score_text = self.font_medium.render(f"Финальный счет: {self.score}", True, WHITE)
score_rect = score_text.get_rect(center=(SCREEN_WIDTH // 2, 230))
self.screen.blit(score_text, score_rect)
congrats = self.font_small.render("Поздравляем! Вы прошли все уровни!", True, CYAN)
congrats_rect = congrats.get_rect(center=(SCREEN_WIDTH // 2, 280))
self.screen.blit(congrats, congrats_rect)
# Кнопки
mouse_pos = pygame.mouse.get_pos()
self.restart_button.check_hover(mouse_pos)
self.menu_button.check_hover(mouse_pos)
self.restart_button.draw(self.screen, self.font_small)
self.menu_button.rect.y = 380
self.menu_button.draw(self.screen, self.font_small)
def draw(self):
"""Отрисовка игры"""
if self.state == "menu":
self.draw_menu()
elif self.state == "playing" or self.state == "paused":
self.draw_background()
# Отрисовка игровых объектов
for block in self.blocks:
block.draw(self.screen)
for powerup in self.powerups:
powerup.draw(self.screen, self.font_small)
self.paddle.draw(self.screen)
for ball in self.balls:
ball.draw(self.screen)
for particle in self.particles:
particle.draw(self.screen)
self.draw_ui()
# Подсказка для запуска мяча
if self.balls and not self.balls[0].active:
hint = self.font_small.render("Нажмите ПРОБЕЛ для запуска", True, WHITE)
hint_rect = hint.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
self.screen.blit(hint, hint_rect)
if self.state == "paused":
self.draw_pause()
elif self.state == "game_over":
self.draw_game_over()
elif self.state == "level_complete":
self.draw_level_complete()
elif self.state == "win":
self.draw_win()
pygame.display.flip()
def handle_events(self):
"""Обработка событий"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = pygame.mouse.get_pos()
if self.state == "menu":
if self.start_button.is_clicked(mouse_pos, True):
self.start_game()
elif self.quit_button.is_clicked(mouse_pos, True):
return False
elif self.state == "paused":
if self.continue_button.is_clicked(mouse_pos, True):
self.state = "playing"
elif self.menu_button.is_clicked(mouse_pos, True):
self.state = "menu"
elif self.state == "game_over":
if self.restart_button.is_clicked(mouse_pos, True):
self.start_game()
elif self.menu_button.is_clicked(mouse_pos, True):
self.state = "menu"
self.menu_button.rect.y = 380
elif self.state == "level_complete":
if self.next_level_button.is_clicked(mouse_pos, True):
self.level += 1
self.lives = 3
self.start_level()
elif self.state == "win":
if self.restart_button.is_clicked(mouse_pos, True):
self.start_game()
elif self.menu_button.is_clicked(mouse_pos, True):
self.state = "menu"
self.menu_button.rect.y = 380
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
if self.state == "playing":
self.state = "paused"
elif self.state == "paused":
self.state = "playing"
if event.key == pygame.K_SPACE and self.state == "playing":
for ball in self.balls:
if not ball.active:
ball.active = True
angle = random.uniform(-30, 30)
ball.dx = BALL_SPEED * math.sin(math.radians(angle))
ball.dy = -BALL_SPEED
return True
def run(self):
"""Основной игровой цикл"""
running = True
while running:
running = self.handle_events()
self.update()
self.draw()
self.clock.tick(FPS)
pygame.quit()
# Запуск игры
if __name__ == "__main__":
game = Game()
game.run()
В финале тестирования модель создаст шифратор и дешифратор для файлов Word.
Скрытый текст


Здесь тоже все идеально: шифры работают корректно, а дешифрация выполняется без проблем. Три теста из трех пройдены на отлично.
Вывод
Что можно сказать насчет Claude Opus 4.5? То же, что и многие успели упомянуть за это время: модель просто поражает своими возможностями в программировании, хотя мое погружение в эту сферу было лишь поверхностным. Пожалуй, в задачах программирования для меня теперь избран однозначный фаворит.
Спасибо за прочтение!

AdrianoVisoccini
Напиши "калькулятор", напиши "арканоид"... ну модель же в данном случае даже не решает задачу в полной мере а просто перебирает уже кем-то реализованные варианты, может вместо арканоида стоит написать:
И посомртреть какой тогда результат будет?
MrRjxrby Автор
Достаточно интересная задумка, попробую.