Claude Haiku 4.5
by AnthropicReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 16.9 s
- Cost
- $0.028
- Output tokens
- 5,462
- Spent thinking
- 0 tokens
- Speed
- 340.9 tok/s
- Console errors
- 0
- First token after
- 828 ms
- First visible text after
- 828 ms
- Prompt tokens
- 524
- Code size
- 17.8 KB
- Finish reason
- stop
- Served by
- Amazon Bedrock
- Model id
anthropic/claude-haiku-4.5- Reasoning sent
{"effort":"none"}- Max output
- 32,000 tokens
- Generated
- Nov 10, 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 · 566 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Snake Game</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
font-family: 'Arial', sans-serif;
}
#gameContainer {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
#scoreBoard {
display: flex;
gap: 40px;
color: white;
font-size: 18px;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}
#scoreBoard div {
display: flex;
flex-direction: column;
align-items: center;
}
#scoreBoard .label {
font-size: 14px;
opacity: 0.9;
}
#scoreBoard .value {
font-size: 28px;
margin-top: 5px;
}
canvas {
border: 4px solid white;
background-color: #1a1a2e;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
display: block;
image-rendering: pixelated;
}
#controls {
color: white;
font-size: 14px;
text-align: center;
opacity: 0.8;
}
#gameOverlay {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.9);
padding: 40px;
border-radius: 10px;
text-align: center;
color: white;
display: none;
z-index: 1000;
min-width: 300px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}
#gameOverlay h1 {
font-size: 48px;
margin-bottom: 20px;
color: #ff6b6b;
}
#gameOverlay .score {
font-size: 24px;
margin: 15px 0;
}
#gameOverlay .label {
font-size: 14px;
opacity: 0.8;
}
#gameOverlay .hint {
font-size: 14px;
margin-top: 25px;
opacity: 0.7;
}
#pauseOverlay {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.9);
padding: 40px;
border-radius: 10px;
text-align: center;
color: white;
display: none;
z-index: 1000;
min-width: 300px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}
#pauseOverlay h1 {
font-size: 48px;
margin-bottom: 20px;
color: #4ecdc4;
}
#pauseOverlay .hint {
font-size: 14px;
margin-top: 15px;
opacity: 0.7;
}
#startOverlay {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.9);
padding: 40px;
border-radius: 10px;
text-align: center;
color: white;
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
z-index: 1000;
min-width: 300px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}
#startOverlay h1 {
font-size: 48px;
color: #ffd700;
}
#startOverlay .hint {
font-size: 16px;
opacity: 0.8;
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 0.8; }
50% { opacity: 1; }
}
@media (max-width: 768px) {
#gameContainer {
gap: 15px;
}
#scoreBoard {
gap: 20px;
font-size: 16px;
}
#scoreBoard .value {
font-size: 24px;
}
canvas {
border: 3px solid white;
}
#gameOverlay, #pauseOverlay, #startOverlay {
padding: 30px;
min-width: 250px;
}
#gameOverlay h1, #pauseOverlay h1, #startOverlay h1 {
font-size: 36px;
}
}
</style>
</head>
<body>
<div id="gameContainer">
<div id="scoreBoard">
<div>
<div class="label">Score</div>
<div class="value" id="currentScore">0</div>
</div>
<div>
<div class="label">Best</div>
<div class="value" id="bestScore">0</div>
</div>
</div>
<canvas id="gameCanvas"></canvas>
<div id="controls">Arrow keys or WASD to move • P to pause • Space/Enter to restart</div>
</div>
<div id="startOverlay">
<h1>🐍 SNAKE</h1>
<div class="hint">Click or press a key to start</div>
</div>
<div id="gameOverlay">
<h1>GAME OVER</h1>
<div class="score">
<div class="label">Final Score</div>
<div id="finalScore">0</div>
</div>
<div class="hint">Press Space or Enter to restart</div>
</div>
<div id="pauseOverlay">
<h1>PAUSED</h1>
<div class="hint">Press P to resume</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// Game constants
const GRID_SIZE = 20;
const CELL_SIZE = 30;
const canvas_width = GRID_SIZE * CELL_SIZE;
const canvas_height = GRID_SIZE * CELL_SIZE;
canvas.width = canvas_width;
canvas.height = canvas_height;
// Game state
let gameState = 'start'; // 'start', 'playing', 'paused', 'gameOver', 'aiDemo'
let score = 0;
let bestScore = 0;
// Snake
let snake = [{ x: 10, y: 10 }];
let direction = { x: 1, y: 0 };
let nextDirection = { x: 1, y: 0 };
// Food
let food = { x: 15, y: 15 };
// Particles for food eating effect
let particles = [];
// Input queue for buffering key presses
let inputQueue = [];
// Game loop timing
let lastMoveTime = 0;
const MOVE_INTERVAL = 100; // ms
// AI demo
let aiMoveCounter = 0;
// Initialize game
function init() {
snake = [{ x: 10, y: 10 }];
direction = { x: 1, y: 0 };
nextDirection = { x: 1, y: 0 };
score = 0;
particles = [];
inputQueue = [];
lastMoveTime = 0;
aiMoveCounter = 0;
spawnFood();
}
// Spawn food at random location not on snake
function spawnFood() {
let newFood;
let valid = false;
while (!valid) {
newFood = {
x: Math.floor(Math.random() * GRID_SIZE),
y: Math.floor(Math.random() * GRID_SIZE)
};
valid = !snake.some(seg => seg.x === newFood.x && seg.y === newFood.y);
}
food = newFood;
}
// Handle keyboard input
document.addEventListener('keydown', (e) => {
const key = e.key.toLowerCase();
if (gameState === 'start') {
if (key === ' ' || key === 'enter' || ['arrowup', 'arrowdown', 'arrowleft', 'arrowright', 'w', 'a', 's', 'd'].includes(key)) {
e.preventDefault();
init();
gameState = 'playing';
document.getElementById('startOverlay').style.display = 'none';
lastMoveTime = Date.now();
}
} else if (gameState === 'gameOver') {
if (key === ' ' || key === 'enter') {
e.preventDefault();
init();
gameState = 'playing';
document.getElementById('gameOverlay').style.display = 'none';
lastMoveTime = Date.now();
}
} else if (gameState === 'paused') {
if (key === 'p') {
e.preventDefault();
gameState = 'playing';
document.getElementById('pauseOverlay').style.display = 'none';
lastMoveTime = Date.now();
}
} else if (gameState === 'playing' || gameState === 'aiDemo') {
if (key === 'p') {
e.preventDefault();
gameState = 'paused';
document.getElementById('pauseOverlay').style.display = 'flex';
} else if (key === ' ' || key === 'enter') {
e.preventDefault();
init();
gameState = 'playing';
document.getElementById('gameOverlay').style.display = 'none';
} else {
handleMove(key);
}
}
});
// Handle move input
function handleMove(key) {
let newDir = null;
if (key === 'arrowup' || key === 'w') newDir = { x: 0, y: -1 };
else if (key === 'arrowdown' || key === 's') newDir = { x: 0, y: 1 };
else if (key === 'arrowleft' || key === 'a') newDir = { x: -1, y: 0 };
else if (key === 'arrowright' || key === 'd') newDir = { x: 1, y: 0 };
if (newDir) {
inputQueue.push(newDir);
}
}
// Update game logic
function update(currentTime) {
if (gameState !== 'playing' && gameState !== 'aiDemo') return;
// Process AI moves in demo mode
if (gameState === 'aiDemo') {
aiMoveCounter++;
if (aiMoveCounter >= 2) {
aiMoveCounter = 0;
const head = snake[0];
const dist = {
up: Math.abs(food.x - head.x) + Math.abs(food.y - 1 - head.y),
down: Math.abs(food.x - head.x) + Math.abs(food.y + 1 - head.y),
left: Math.abs(food.x - 1 - head.x) + Math.abs(food.y - head.y),
right: Math.abs(food.x + 1 - head.x) + Math.abs(food.y - head.y)
};
const minDist = Math.min(dist.up, dist.down, dist.left, dist.right);
if (minDist === dist.up && direction.y === 0) nextDirection = { x: 0, y: -1 };
else if (minDist === dist.down && direction.y === 0) nextDirection = { x: 0, y: 1 };
else if (minDist === dist.left && direction.x === 0) nextDirection = { x: -1, y: 0 };
else if (minDist === dist.right && direction.x === 0) nextDirection = { x: 1, y: 0 };
}
} else {
// Process input queue
if (inputQueue.length > 0) {
const newDir = inputQueue.shift();
// Prevent reversing
if (!(newDir.x === -direction.x && newDir.y === -direction.y)) {
nextDirection = newDir;
}
}
}
// Move snake
if (currentTime - lastMoveTime > MOVE_INTERVAL) {
direction = nextDirection;
const head = snake[0];
const newHead = {
x: head.x + direction.x,
y: head.y + direction.y
};
// Check wall collision
if (newHead.x < 0 || newHead.x >= GRID_SIZE || newHead.y < 0 || newHead.y >= GRID_SIZE) {
endGame();
return;
}
// Check self collision
if (snake.some(seg => seg.x === newHead.x && seg.y === newHead.y)) {
endGame();
return;
}
snake.unshift(newHead);
// Check food collision
if (newHead.x === food.x && newHead.y === food.y) {
score += 10;
document.getElementById('currentScore').textContent = score;
if (score > bestScore) {
bestScore = score;
document.getElementById('bestScore').textContent = bestScore;
}
createParticles(food.x * CELL_SIZE + CELL_SIZE / 2, food.y * CELL_SIZE + CELL_SIZE / 2);
spawnFood();
} else {
snake.pop();
}
lastMoveTime = currentTime;
}
// Update particles
particles = particles.filter(p => {
p.life -= 0.02;
return p.life > 0;
});
}
// Create particle burst
function createParticles(x, y) {
for (let i = 0; i < 8; i++) {
const angle = (Math.PI * 2 * i) / 8;
particles.push({
x: x,
y: y,
vx: Math.cos(angle) * 3,
vy: Math.sin(angle) * 3,
life: 1
});
}
}
// End game
function endGame() {
gameState = 'gameOver';
document.getElementById('finalScore').textContent = score;
document.getElementById('gameOverlay').style.display = 'flex';
}
// Draw game
function draw() {
// Clear canvas
ctx.fillStyle = '#1a1a2e';
ctx.fillRect(0, 0, canvas_width, canvas_height);
// Draw grid (faint)
ctx.strokeStyle = 'rgba(255, 255, 255, 0.05)';
ctx.lineWidth = 1;
for (let i = 0; i <= GRID_SIZE; i++) {
ctx.beginPath();
ctx.moveTo(i * CELL_SIZE, 0);
ctx.lineTo(i * CELL_SIZE, canvas_height);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, i * CELL_SIZE);
ctx.lineTo(canvas_width, i * CELL_SIZE);
ctx.stroke();
}
// Draw food
ctx.fillStyle = '#ff6b6b';
ctx.beginPath();
ctx.arc(food.x * CELL_SIZE + CELL_SIZE / 2, food.y * CELL_SIZE + CELL_SIZE / 2, CELL_SIZE / 2 - 2, 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = '#ff4444';
ctx.lineWidth = 2;
ctx.stroke();
// Draw snake
snake.forEach((seg, index) => {
const x = seg.x * CELL_SIZE;
const y = seg.y * CELL_SIZE;
if (index === 0) {
// Draw head
ctx.fillStyle = '#4ecdc4';
ctx.fillRect(x + 1, y + 1, CELL_SIZE - 2, CELL_SIZE - 2);
// Draw eyes
ctx.fillStyle = '#ffffff';
const eyeSize = 4;
const eyeOffset = 5;
let eyeX1, eyeY1, eyeX2, eyeY2;
if (direction.x === 1) { // Right
eyeX1 = x + CELL_SIZE - eyeOffset;
eyeY1 = y + eyeOffset;
eyeX2 = x + CELL_SIZE - eyeOffset;
eyeY2 = y + CELL_SIZE - eyeOffset;
} else if (direction.x === -1) { // Left
eyeX1 = x + eyeOffset;
eyeY1 = y + eyeOffset;
eyeX2 = x + eyeOffset;
eyeY2 = y + CELL_SIZE - eyeOffset;
} else if (direction.y === -1) { // Up
eyeX1 = x + eyeOffset;
eyeY1 = y + eyeOffset;
eyeX2 = x + CELL_SIZE - eyeOffset;
eyeY2 = y + eyeOffset;
} else { // Down
eyeX1 = x + eyeOffset;
eyeY1 = y + CELL_SIZE - eyeOffset;
eyeX2 = x + CELL_SIZE - eyeOffset;
eyeY2 = y + CELL_SIZE - eyeOffset;
}
ctx.fillRect(eyeX1 - eyeSize / 2, eyeY1 - eyeSize / 2, eyeSize, eyeSize);
ctx.fillRect(eyeX2 - eyeSize / 2, eyeY2 - eyeSize / 2, eyeSize, eyeSize);
} else {
// Draw body
ctx.fillStyle = index === 1 ? '#45b7aa' : '#3a9e92';
ctx.fillRect(x + 2, y + 2, CELL_SIZE - 4, CELL_SIZE - 4);
ctx.strokeStyle = '#2a7e72';
ctx.lineWidth = 1;
ctx.strokeRect(x + 2, y + 2, CELL_SIZE - 4, CELL_SIZE - 4);
}
});
// Draw particles
particles.forEach(p => {
p.x += p.vx;
p.y += p.vy;
ctx.fillStyle = `rgba(255, 107, 107, ${p.life * 0.7})`;
const size = 3 * p.life;
ctx.fillRect(p.x - size / 2, p.y - size / 2, size, size);
});
}
// Game loop
function gameLoop(currentTime) {
update(currentTime);
draw();
requestAnimationFrame(gameLoop);
}
// Start AI demo
function startAIDemo() {
gameState = 'aiDemo';
init();
lastMoveTime = Date.now();
}
// Initialize
startAIDemo();
requestAnimationFrame(gameLoop);
</script>
</body>
</html>