Подписывайтесь:

Блог AST-SoftPro

Тест «Змейки» на 38 локальных LLM: одна игра, два результата — почему Qwen 3.8-27B победила с первого прогона

15.08.2026 15 мин чтения
Тест «Змейки» на 38 локальных LLM: одна игра, два результата — почему Qwen 3.8-27B победила с первого прогона

«Сделай игру Змейку одним HTML-файлом» — популярный тест на генерацию кода. Мы прогнали его через 38 локальных LLM (от 7B до REAP-pruned моделей в ~140B активных параметров) и получили разделительную картину: 21 модель сдала рабочую игру, 16 — не запустились по конкретным техническим причинам. Победителем по оформлению стал Qwen 3.8-27B в квантовании Q4_K_M на связке из двух RTX 5060 Ti 16 ГБ: он сгенерировал неоновую аркаду со звуком, частицами и мобильными жестами с первого прогона — без единой правки.

В этой статье — полный список моделей по группам, реальные баги в «не рабочих» файлах и анализ, что именно отличает победителей от провалов.

Промпт: одинаковый для всех 38 моделей

Оригинальный текст запроса (на английском, без изменений):

Act as an expert front-end developer. Build a complete, fully functional, and visually polished Snake game contained within a single HTML file.

The code must include the HTML structure, CSS styling, and JavaScript logic together. Ensure there are no placeholders, no missing functions, and no external dependencies or CDNs required.

### Technical Requirements:

1. Architecture: Use a <canvas> element for rendering the game board grid.

2. Responsiveness: Center the game board on the screen. It must look clean on both desktop and mobile layouts.

3. Controls:
   - Keyboard: Arrow keys and WASD for movement. Prevent default browser scrolling when these keys are pressed.
   - Mobile: Include visible, on-screen touch buttons (Up, Down, Left, Right) that map to the controls.

4. Game Loop: Use requestAnimationFrame() or a reliable setInterval() loop to control the snake's speed smoothly.

### Game Rules & Mechanics:

- Start the snake at a fixed length (e.g., 3 blocks long) moving right.

- Spawn food at a random grid position. Ensure food never spawns directly on top of the snake's body.

- When the snake eats food, increase its length by 1, increment the score, and spawn a new piece of food.

- Implement collision detection: The game ends if the snake hits the outer walls or runs into its own body.

### UI & UX Polish:

- Sidebar or Top Bar: Display the "Current Score" and a persistent "High Score" (saved in localStorage).

- Screens: Include an overlay screen for "Press Start to Play" and a "Game Over" screen featuring a prominent "Restart" button.

- Aesthetics: Apply a modern dark theme (e.g., dark gray background, neon green snake, vibrant red food, crisp modern font).

Return ONLY the complete HTML code wrapped in a single ```html codeblock. Do not include markdown explanations outside of the codeblock.

Коротко по смыслу: один HTML-файл; canvas для игрового поля; центрирование и адаптивность под desktop/mobile; управление стрелками + WASD (с preventDefault от скролла) и видимые touch-кнопки Up/Down/Left/Right; игровой цикл на requestAnimationFrame или setInterval; змейка стартует длиной 3 вправо; еда — случайная клетка, не под телом; при съедании +1 к длине, счёт растёт, спавнится новая еда; столкновение со стеной или с собой = конец игры; боковая/верхняя панель с Current Score и High Score (localStorage); оверлей «Press Start to Play» и экран «Game Over» с заметной кнопкой Restart; современный тёмный стиль (тёмно-серый фон, неоновая зелёная змейка, ярко-красная еда, чёткий шрифт). В ответе — только полный HTML внутри одного блока.

Сознательно не требовали «красивости», анимаций или звука сверх ТЗ — чистый функциональный запрос. Всё лишнее модель добавляет сама, и именно это стало критерием субъективной оценки.

Результаты: 21 рабочая / 16 нерабочих

Результаты разделены на две группы: work — игра открывается и играбельна, not-work — не запускается или неиграбельна.

Рабочие — 21 модель

Модель Размер snake.html Примечание по оформлению
unsloth-qwen3.8-27b-q4_k_m 33 927 Б Неоновая аркада: звук WebAudio, частицы, тряска экрана, d-pad + свайпы, пауза (P), mute, prefers-reduced-motion — лучшее оформление
Cerebras-qwen3.5-122b-REAP-MTP ≈30 Кб Крупная REAP-pruned модель, функционально сильна, но без полировки
cerebras_GLM-4.5-Air-REAP-82B-A12B-IQ4_XS ≈26 Кб Аккуратный UI, тёмная тема
Cerebras-Step-3.5-Flash-REAP ≈20 Кб Чистый минимализм
unsloth-Qwen3.6-27B-Q6_K-GGUF ≈18 Кб Рабочий базовый набор + градиент тела
Qwopus3.6-27B-Coder-MTP-Q6_K / GGUF ≈17–19 Кб Стабильный результат coder-линейки
dagger-qwen3.6-27b ≈15 Кб Функциональная, без лишнего
Q3.6-27B-GLM-5.1-DA.Q6_K ≈14 Кб Стандартный тёмный UI
qwopus3.6-27b-coder-compat-mtp / grug-27b-mtp.i1-Q6_K ≈13–14 Кб Рабочие MTP-варианты 27B
ornith-1.0-35b / ornith-1.0-35b-nvfp4-mtp ≈13–16 Кб Неплохая сетка, плавное движение
qwen-agentworld-35b-a3b / nail-qwen3.6-35b-a3b ≈12–14 Кб MoE 35B-A3B: быстрее при меньшем качестве полировки
qwen3.5-9b-mtp ≈11 Кб Лучший из малых (≤10B) по соотношению размер/качество
google-gemma-4-26b-a4b-qat / gemma-4-31B-it-Q4_K_M-GGUF ≈12–15 Кб Стабильные 26/31B от Google
google-gemma-4-12b ≈9 Кб Рабочая для своего размера
Ternary-Bonsai-27b-q2_0 ≈8 Кб Агрессивное квантование q2_0 — и всё равно играбельно
nex-n2-mini / michaelw9999-Qwen3.6-27B-NVFP4-MTP-GGUF ≈10–12 Кб Прочный средний класс

Нерабочие — 16 моделей и конкретные баги

Модель Размер Причина отказа
qwen3.5-9b-deepseek-v4-flash-mtp 16 469 Б Fall-through в switch: между кейсами up/down/left/right нет оператора break, направление «скатывается» через все ветки, и змейка сразу умирает или летит не туда
openai-gpt-oss-20b 5 315 Б ctx.fillStyle='var(--bg)' — CSS-переменная в canvas fillStyle; канвас рисуется чёрным/прозрачным. Плюс setTimeout внутри rAF ломает ритм, а переменная gameOver используется до объявления (hoisting)
qwen2.5-coder-7b-instruct 4 020 Б Автозапуск: document.querySelector('.overlay button').click() в конце скрипта — игра стартует мгновенно, оверлей не показывается; к тому же setInterval ссылается на глобальный event, которого нет
nvidia-nemotron-3.5-lightning-30b-a3b 12 921 Б Неправильная геометрия еды: радиус fr = Math.min(canvas.width, canvas.height) / 2 - 4 — еда размером с полканваса вместо одного тайла (нужно canvas.width / GRID_SIZE)
qwopus3.5-9b-coder ≈10 Кб Пропущена обработка столкновения со стеной: змейка проходит сквозь границу, игра не заканчивается
qwen-qwen2.5-coder-14b ≈9 Кб Оверлей «Game Over» не показывается — отсутствует смена display; после смерти ничего не происходит
t-lite-it-2.1 ≈8 Кб Управление WASD сломано: слушается только e.key === 'w' без .toLowerCase() — заглавные буквы (CapsLock) игнорируются
zai-org-glm-4.6v-flash ≈9 Кб Еда не спавнится после первого съедания — вызов spawnFood() отсутствует в ветке «съел»
Qwopus3.6-27B-Coder-MTP-NVFP4-TURBO ≈12 Кб 27B, но сбой: дублирующийся requestAnimationFrame-цикл после рестарта — две скорости движения одновременно, змейка «дёргается» и съедает себя на 3-м шаге
qwythos-9b-claude-mythos-5-1m ≈7 Кб Мобильные кнопки не привязаны к nextDirection — touch не работает, играбельно только с клавиатуры (требование ТЗ нарушено)
m51Lab-MiniMax-M2.7-REAP-139B-A10B.Q2_K-GGUF ≈18 Кб Рекорд по размеру среди провалов: при 139B активных параметров Q2_K квантование убило логику — счёт не инкрементируется, highscore не пишется в localStorage
nvidia-nemotron-3-nano ≈6 Кб Змейка стартует с одной клетки вместо трёх (требование ТЗ), еда может спавниться под головой
gigachat3.1-lightning-uncensored-i1 ≈8 Кб snake.unshift(head) без последующего pop() — змейка растёт на каждом тике, заполняет поле за ~60 кадров и всегда «проигрывает» сама себе
google-gemma-4-e4b ≈5 Кб Еда рендерится вне canvas: координаты вычисляются в пикселях вместо тайлов (food.x без умножения на tileSize) — красный квадрат за пределами игрового поля
openai_gpt_oss_120b_pruned_reap_58b ≈11 Кб Порядок условий инвертирован: коллизия со стеной проверяется после unshift, а проверка еды — до неё; при съедании еды у стены игра убивает, даже если удар в стену не состоялся
NVIDIA-Nemotron-3-Nano-Omni-30B-A3B-Reasoning-Q8_0 ≈14 Кб Reasoning-режим выдал длинное размышление, но финальный HTML обрезан — незакрытый </script>, браузер не парсит скрипт

Что отличает победителей от провалов

Разбирая 38 файлов по коду, выделили пять повторяющихся паттернов неудач:

  1. CSS-переменные в canvas (gpt-oss-20b и др.) — LLM переносит веб-стиль в 2D API. fillStyle принимает только конкретные цвета/градиенты, а не var(--bg). Модели с «веб-фокусом» в корпусе чаще всего падают именно здесь.

  2. Fall-through в switch без break (qwen3.5-9b-deepseek-v4-flash-mtp и др.) — классическая ошибка C/JS, которую LLMы копируют из фрагментов обучающих данных. Частота растёт у 7–10B моделей.

  3. Неправильная геометрия еды (nvidia-nemotron-3.5-lightning) — модель путает «радиус круглого предмета» и «размер тайла сетки». В итоге еда не на своём месте или размером с полканваса.

  4. Состояние после рестарта (Qwopus3.6-27B-Coder-MTP-NVFP4-TURBO) — двойной игровой цикл: requestAnimationFrame не останавливается при game over, и после кнопки «Рестарт» крутятся два цикла одновременно. Это редкий, но смертельный сценарий.

  5. Нарушение явных пунктов ТЗ (t-lite-it-2.1, qwythos-9b) — не работают touch-кнопки, WASD сломан из-за регистра, змейка стартует не с трёх сегментов. Модель «решает задачу по-своему», игнорируя требования промпта.

Почему же Qwen 3.8-27B Q4_K_M дала лучший результат? По нашему наблюдению:

  • Длинное размышление (~32K токенов reasoning) до кода — модель явно «проектировала» архитектуру игры (система частиц, звук через WebAudio, пауза, мобильные жесты), а не генерировала код строка за строкой.

  • Гибрид DeltaNet экономит KV-кэш на длинных развёртках — 32K токенов рассуждений поместились в контекст без деградации качества (на чистых attention-моделях такого размера 32K reasoning часто «теряют» начальные пункты ТЗ).

  • Q4_K_M при ~17 ГБ оставил на двух RTX 5060 Ti запас под KV-кэш — без обрезки контекста и троттлинга.

Итоги по размерам моделей

Класс модели Рабочих / всего в классе Средний «уровень» результата
≤ 10B (9–14B) 3 из ~7 Базовая играбельность, без полировки; частые баги управления и геометрии
12–35B dense 8 из ~13 Функциональная игра; 2–3 модели с хорошим оформлением (qwen3.8-27b — лучший)
MoE A3B / A12B (активных параметров мало) 4 из ~6 Быстро, но качество уступает dense-коллегам того же «именового» размера
REAP-pruned ≥ 50B 4 из 8 Большой размер ≠ надёжность: Q2_K квантование ломает логику (MiniMax-M2.7-REAP), NVFP4-TURBO даёт дублирующий цикл

Вывод

«Змейка одним файлом» — не тривиальный тест. Из 38 локальных моделей только 55% дали играбельный результат, а в рабочей половине лишь Qwen 3.8-27B Q4_K_M закрыла ТЗ полностью и ещё добавила полировку (звук, частицы, жесты) сверх запроса. Для владельцев двух RTX 5060 Ti по 16 ГБ это практически бесплатная альтернатива дорогим API: один прогон ≈ 22 минуты генерации при 24 т/с — и игра уровня маленькой веб-аркады без единой правки.

Отдельные статьи с полным разбором каждой модели, скриншотами и кодом — в нашей серии по локальным LLM. Промпт приведён выше полностью; результаты разделены на группы work / not-work для воспроизведения теста любой читательской связкой.

Источники

  1. Hugging Face — карточки использованных моделей (Unsloth GGUF, Cerebras REAP, Qwen): https://huggingface.co/models

  2. Документация llama.cpp по multi-GPU tensor split: https://github.com/ggml-org/llama.cpp/wiki

  3. Web Audio API — спецификация MDN для реализации звуковых эффектов в игре: https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API

  4. CanvasRenderingContext2D.fillStyle — допустимые значения (MDN), объясняющие баг с var(--bg): https://developer.mozilla.org/ru/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes

  5. requestAnimationFrame — MDN, игровой цикл в HTML5-играх: https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame

AI-Помощник