DeepSeek V4 Flash 0423
by DeepSeekreasoning defaultClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 29.6 s
- Cost
- $0.0010
- Output tokens
- 5,268
- Spent thinking
- 0 tokens
- Speed
- 181.9 tok/s
- Console errors
- 0
- First token after
- 641 ms
- First visible text after
- 641 ms
- Prompt tokens
- 492
- Code size
- 16.1 KB
- Finish reason
- stop
- Served by
- Wafer
- Model id
deepseek/deepseek-v4-flash- Reasoning sent
model default- Max output
- 393,216 tokens
- Generated
- Nov 13, 2026
What it was asked
The prompt
Build a polished Snake game in a single HTML file using vanilla JavaScript and a <canvas>. Requirements: - A grid of at least 20×20 cells, centered on the page. - Arrow keys and WASD control the snake. Quick successive key presses must both be honored, but the snake can never reverse onto itself. - Eating food adds 10 points and grows the snake by one cell; new food never spawns on the snake. - Game over when the snake hits a wall or itself, with an overlay showing the score; Space or Enter restarts, P pauses. - Visual polish: smooth movement, a snake with a distinct head and eyes facing its direction, and a small particle burst when eating. - Display the current score and the best score of the session.
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task. Output rules: - Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block. - Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task. - Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw. - The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar. - Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction. - Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session. - Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing. - The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message. - The code must run with zero errors in the console of the latest Chrome.
Code run-1.html · 543 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Snake · polished</title>
<style>
* {
box-sizing: border-box;
user-select: none;
}
body {
margin: 0;
min-height: 100vh;
background: linear-gradient(145deg, #111418, #1f2a30);
display: flex;
align-items: center;
justify-content: center;
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
}
.game-wrapper {
background: #1e2a2f;
padding: 1.6rem 1.6rem 1.8rem;
border-radius: 3.5rem;
box-shadow: 0 20px 30px rgba(0,0,0,0.7), inset 0 1px 3px rgba(255,255,255,0.08);
backdrop-filter: blur(2px);
}
.header {
display: flex;
justify-content: space-between;
align-items: baseline;
padding: 0 0.5rem 0.8rem 0.5rem;
color: #c8ddd0;
font-weight: 500;
letter-spacing: 0.3px;
text-shadow: 0 2px 3px #0b1113;
}
.score-span {
background: #0e1a1e;
padding: 0.3rem 1.2rem;
border-radius: 40px;
box-shadow: inset 0 3px 6px rgba(0,0,0,0.6), 0 1px 0 #497b6b;
font-size: 1.2rem;
display: inline-block;
}
.score-label {
opacity: 0.7;
font-size: 0.85rem;
margin-right: 6px;
}
canvas {
display: block;
margin: 0 auto;
width: 560px;
height: 560px;
border-radius: 28px;
background: #1d2b30;
box-shadow: inset 0 0 0 2px #2d4148, 0 12px 20px -8px black;
cursor: pointer;
touch-action: none;
}
.status-bar {
display: flex;
justify-content: space-between;
padding: 0.8rem 0.5rem 0 0.5rem;
color: #9fb7af;
font-size: 0.9rem;
font-weight: 400;
}
.best-score {
background: #0f1b1f;
padding: 0.2rem 1rem;
border-radius: 30px;
box-shadow: inset 0 2px 5px #0a1215;
}
.controls-hint {
opacity: 0.6;
letter-spacing: 0.5px;
}
@media (max-width: 600px) {
.game-wrapper { padding: 1rem; border-radius: 2rem; }
canvas { width: 92vw; height: 92vw; max-width: 500px; max-height: 500px; }
.header { flex-wrap: wrap; gap: 0.3rem; }
}
</style>
</head>
<body>
<div class="game-wrapper">
<div class="header">
<div class="score-span"><span class="score-label">🍎</span><span id="scoreDisplay">0</span></div>
<div class="score-span"><span class="score-label">🏆</span><span id="bestDisplay">0</span></div>
</div>
<canvas id="gameCanvas" width="560" height="560"></canvas>
<div class="status-bar">
<span class="controls-hint">←↑↓→ / WASD</span>
<span id="pauseIndicator">▶</span>
</div>
</div>
<script>
(function(){
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreSpan = document.getElementById('scoreDisplay');
const bestSpan = document.getElementById('bestDisplay');
const pauseIndicator = document.getElementById('pauseIndicator');
// ---------- constants ----------
const GRID = 20; // 20x20
const CELL = 28; // pixel size (560/20)
const TICK_BASE = 150; // ms per frame
// ---------- state ----------
let snake = []; // [{x,y}] head first
let food = { x: 8, y: 8 };
let direction = { x: 1, y: 0 }; // current direction
let nextDirection = { x: 1, y: 0 };
let score = 0;
let bestScore = 0;
let gameActive = false; // true = playing, false = game over / waiting
let gameOverFlag = false;
let winFlag = false; // (not used, but for safety)
let paused = false;
// particles
let particles = [];
// timing
let lastMove = 0;
let animationFrame = null;
let startScreen = true; // show "click to start"
// key buffer: allow up to 2 buffered inputs (prevents reverse)
let keyBuffer = [];
// ---------- helpers ----------
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getFreeCell() {
const occupied = new Set(snake.map(s => `${s.x},${s.y}`));
const free = [];
for (let i = 0; i < GRID; i++) {
for (let j = 0; j < GRID; j++) {
if (!occupied.has(`${i},${j}`)) free.push({ x: i, y: j });
}
}
if (free.length === 0) return null;
return free[Math.floor(Math.random() * free.length)];
}
function spawnFood() {
const cell = getFreeCell();
if (!cell) {
// you win – but we treat as game over (full map)
gameOverFlag = true;
gameActive = false;
return false;
}
food = cell;
return true;
}
// ---------- reset / init ----------
function resetGame() {
snake = [
{ x: 9, y: 10 },
{ x: 8, y: 10 },
{ x: 7, y: 10 }
];
direction = { x: 1, y: 0 };
nextDirection = { x: 1, y: 0 };
score = 0;
gameOverFlag = false;
gameActive = true;
paused = false;
startScreen = false;
keyBuffer = [];
particles = [];
if (!spawnFood()) {
// map full → rare, but reset again
snake = [{ x: 5, y: 5 }, { x: 4, y: 5 }, { x: 3, y: 5 }];
spawnFood();
}
updateScoreUI();
pauseIndicator.textContent = '▶';
}
function gameOver() {
gameActive = false;
gameOverFlag = true;
if (score > bestScore) {
bestScore = score;
bestSpan.textContent = bestScore;
}
pauseIndicator.textContent = '⏹';
}
// ---------- movement & collision ----------
function moveSnake() {
if (!gameActive || paused || gameOverFlag) return false;
// consume buffered direction (at least one)
if (keyBuffer.length > 0) {
const newDir = keyBuffer.shift();
// prevent reversal
if (!(newDir.x === -direction.x && newDir.y === -direction.y)) {
direction = { ...newDir };
}
}
const head = snake[0];
const newHead = {
x: head.x + direction.x,
y: head.y + direction.y
};
// wall collision
if (newHead.x < 0 || newHead.x >= GRID || newHead.y < 0 || newHead.y >= GRID) {
gameOver();
return false;
}
// self collision (check against current snake body, excluding tail if not growing)
const willEat = (newHead.x === food.x && newHead.y === food.y);
// if will eat, tail stays; else tail will be removed – so collision check against body without last element
const compareBody = willEat ? snake : snake.slice(0, -1);
for (let seg of compareBody) {
if (seg.x === newHead.x && seg.y === newHead.y) {
gameOver();
return false;
}
}
// perform move
snake.unshift(newHead);
if (willEat) {
// eat: grow (keep tail)
score += 10;
updateScoreUI();
spawnParticles(food.x * CELL + CELL/2, food.y * CELL + CELL/2);
if (!spawnFood()) {
// board full – win condition rare; set gameover but show win style
gameOverFlag = true;
gameActive = false;
return true;
}
} else {
// no food: pop tail
snake.pop();
}
return true;
}
// ---------- particles ----------
function spawnParticles(cx, cy) {
for (let i = 0; i < 18; i++) {
const angle = Math.random() * 2 * Math.PI;
const speed = 1.8 + Math.random() * 3.5;
particles.push({
x: cx,
y: cy,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed,
life: 1.0,
size: 4 + Math.random() * 7,
color: `hsl(${30 + Math.random() * 30}, 85%, ${60 + 30 * Math.random()}%)`
});
}
}
function updateParticles() {
for (let i = particles.length - 1; i >= 0; i--) {
const p = particles[i];
p.x += p.vx;
p.y += p.vy;
p.vy += 0.08;
p.life -= 0.025;
if (p.life <= 0 || p.x < 0 || p.x > 560 || p.y < 0 || p.y > 560) {
particles.splice(i, 1);
}
}
}
// ---------- drawing ----------
function draw() {
ctx.clearRect(0, 0, 560, 560);
// draw subtle grid
ctx.strokeStyle = '#2c3f47';
ctx.lineWidth = 0.7;
for (let i = 0; i <= GRID; i++) {
ctx.beginPath();
ctx.moveTo(i * CELL, 0);
ctx.lineTo(i * CELL, 560);
ctx.strokeStyle = '#304a52';
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, i * CELL);
ctx.lineTo(560, i * CELL);
ctx.strokeStyle = '#304a52';
ctx.stroke();
}
// draw food (glowing)
ctx.shadowColor = '#ffb07c';
ctx.shadowBlur = 14;
ctx.fillStyle = '#ff6f3c';
ctx.beginPath();
ctx.arc(food.x * CELL + CELL/2, food.y * CELL + CELL/2, CELL/2 - 2, 0, 2*Math.PI);
ctx.fill();
ctx.shadowBlur = 0;
// inner shine
ctx.fillStyle = '#ff9a5e';
ctx.beginPath();
ctx.arc(food.x * CELL + CELL/2 - 2, food.y * CELL + CELL/2 - 2, 5, 0, 2*Math.PI);
ctx.fill();
// draw snake
for (let i = 0; i < snake.length; i++) {
const seg = snake[i];
const x = seg.x * CELL, y = seg.y * CELL;
const radius = CELL/2 - 1.5;
// body gradient
const gradient = ctx.createRadialGradient(x+6, y+6, 2, x+10, y+10, 16);
if (i === 0) {
gradient.addColorStop(0, '#78c2a4');
gradient.addColorStop(0.7, '#2c7a5c');
gradient.addColorStop(1, '#1e5f46');
} else {
gradient.addColorStop(0, '#5ca88c');
gradient.addColorStop(0.8, '#2a6f56');
}
ctx.fillStyle = gradient;
ctx.shadowColor = '#1a2b28';
ctx.shadowBlur = 10;
ctx.beginPath();
ctx.roundRect(x+1.5, y+1.5, CELL-3, CELL-3, 8);
ctx.fill();
// eyes on head
if (i === 0) {
ctx.shadowBlur = 0;
const eyeOff = 5;
let ex1, ey1, ex2, ey2;
if (direction.x === 1) { // right
ex1 = x + 18; ey1 = y + 7;
ex2 = x + 18; ey2 = y + 16;
} else if (direction.x === -1) { // left
ex1 = x + 9; ey1 = y + 7;
ex2 = x + 9; ey2 = y + 16;
} else if (direction.y === -1) { // up
ex1 = x + 7; ey1 = y + 9;
ex2 = x + 16; ey2 = y + 9;
} else { // down
ex1 = x + 7; ey1 = y + 18;
ex2 = x + 16; ey2 = y + 18;
}
ctx.fillStyle = '#fffaec';
ctx.beginPath();
ctx.arc(ex1, ey1, 3.5, 0, 2*Math.PI);
ctx.fill();
ctx.beginPath();
ctx.arc(ex2, ey2, 3.5, 0, 2*Math.PI);
ctx.fill();
ctx.fillStyle = '#0f1a1a';
ctx.beginPath();
ctx.arc(ex1 + (direction.x===1?1: direction.x===-1?-1:0), ey1 + (direction.y===1?1: direction.y===-1?-1:0), 1.8, 0, 2*Math.PI);
ctx.fill();
ctx.beginPath();
ctx.arc(ex2 + (direction.x===1?1: direction.x===-1?-1:0), ey2 + (direction.y===1?1: direction.y===-1?-1:0), 1.8, 0, 2*Math.PI);
ctx.fill();
}
}
ctx.shadowBlur = 0;
// particles
for (let p of particles) {
ctx.globalAlpha = p.life;
ctx.fillStyle = p.color;
ctx.beginPath();
ctx.arc(p.x, p.y, p.size * p.life * 0.7, 0, 2*Math.PI);
ctx.fill();
}
ctx.globalAlpha = 1.0;
// overlay game over / start
if (!gameActive && !startScreen) {
ctx.fillStyle = 'rgba(8, 16, 18, 0.75)';
ctx.fillRect(0, 0, 560, 560);
ctx.fillStyle = '#ddeee0';
ctx.font = 'bold 28px "Segoe UI", system-ui, sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('💀 GAME OVER', 280, 250);
ctx.font = '18px sans-serif';
ctx.fillStyle = '#b3d3c5';
ctx.fillText(`score: ${score} · press SPACE / ENTER`, 280, 320);
} else if (startScreen) {
ctx.fillStyle = 'rgba(10, 20, 22, 0.7)';
ctx.fillRect(0, 0, 560, 560);
ctx.fillStyle = '#f5fcf5';
ctx.font = 'bold 26px "Segoe UI", sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('🐍 SNAKE', 280, 220);
ctx.font = '20px sans-serif';
ctx.fillStyle = '#b7d9cf';
ctx.fillText('click or press any key', 280, 300);
ctx.font = '16px sans-serif';
ctx.fillStyle = '#88ada1';
ctx.fillText('arrows / WASD · P pause', 280, 360);
} else if (paused && gameActive) {
ctx.fillStyle = 'rgba(0,0,0,0.3)';
ctx.fillRect(0, 0, 560, 560);
ctx.fillStyle = '#deefe8';
ctx.font = 'bold 30px sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('⏸ PAUSED', 280, 280);
}
}
// roundRect polyfill for canvas
if (!CanvasRenderingContext2D.prototype.roundRect) {
CanvasRenderingContext2D.prototype.roundRect = function(x, y, w, h, r) {
if (r > w/2) r = w/2;
if (r > h/2) r = h/2;
this.moveTo(x + r, y);
this.lineTo(x + w - r, y);
this.quadraticCurveTo(x + w, y, x + w, y + r);
this.lineTo(x + w, y + h - r);
this.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
this.lineTo(x + r, y + h);
this.quadraticCurveTo(x, y + h, x, y + h - r);
this.lineTo(x, y + r);
this.quadraticCurveTo(x, y, x + r, y);
return this;
};
}
// ---------- UI ----------
function updateScoreUI() {
scoreSpan.textContent = score;
if (score > bestScore) bestScore = score;
bestSpan.textContent = bestScore;
}
// ---------- game loop ----------
function tick(now) {
animationFrame = requestAnimationFrame(tick);
if (gameActive && !paused && !gameOverFlag) {
if (now - lastMove > TICK_BASE) {
lastMove = now;
moveSnake();
updateParticles();
updateScoreUI();
} else {
updateParticles();
}
} else {
updateParticles();
}
draw();
}
// ---------- input ----------
function handleKey(e) {
const key = e.key;
// restart / start
if (key === ' ' || key === 'Space' || key === 'Enter') {
e.preventDefault();
if (startScreen || gameOverFlag) {
resetGame();
return;
}
if (!gameActive && gameOverFlag) resetGame();
return;
}
if (key === 'p' || key === 'P') {
if (gameActive && !gameOverFlag) {
paused = !paused;
pauseIndicator.textContent = paused ? '⏸' : '▶';
}
e.preventDefault();
return;
}
// start game on any key if startScreen
if (startScreen) {
resetGame();
return;
}
// directional keys
let dir = null;
if (key === 'ArrowUp' || key === 'w' || key === 'W') dir = { x: 0, y: -1 };
else if (key === 'ArrowDown' || key === 's' || key === 'S') dir = { x: 0, y: 1 };
else if (key === 'ArrowLeft' || key === 'a' || key === 'A') dir = { x: -1, y: 0 };
else if (key === 'ArrowRight' || key === 'd' || key === 'D') dir = { x: 1, y: 0 };
if (dir) {
e.preventDefault();
if (!gameActive || paused || gameOverFlag) return;
// buffer at most 2 inputs
if (keyBuffer.length < 2) {
const last = keyBuffer.length > 0 ? keyBuffer[keyBuffer.length-1] : direction;
if (!(dir.x === -last.x && dir.y === -last.y)) {
keyBuffer.push(dir);
}
}
}
}
function handleClick(e) {
if (startScreen || gameOverFlag) {
resetGame();
}
}
// ---------- init ----------
window.addEventListener('keydown', handleKey);
canvas.addEventListener('click', handleClick);
canvas.addEventListener('touchstart', (e) => {
e.preventDefault();
handleClick(e);
});
// initial best from storage? session-level, but simple: 0
bestScore = 0;
resetGame();
startScreen = true;
gameActive = false;
lastMove = performance.now();
animationFrame = requestAnimationFrame(tick);
})();
</script>
</body>
</html>