```html Snake Game

Snake Game

Score: 0
``` ```typescript // snake.ts content enum Direction { UP = 'UP', DOWN = 'DOWN', LEFT = 'LEFT', RIGHT = 'RIGHT' } class SnakeGame { private canvas: HTMLCanvasElement; private ctx: CanvasRenderingContext2D; private scoreElement: HTMLElement; private gridSize: number = 20; private gridWidth: number; private gridHeight: number; private snake: { x: number; y: number }[]; private direction: Direction; private nextDirection: Direction; private food: { x: number; y: number }; private score: number; private gameInterval: number | null = null; private isGameOver: boolean = false; constructor() { this.canvas = document.getElementById('gameCanvas') as HTMLCanvasElement; this.ctx = this.canvas.getContext('2d') as CanvasRenderingContext2D; this.scoreElement = document.getElementById('score') as HTMLElement; this.gridWidth = this.canvas.width / this.gridSize; this.gridHeight = this.canvas.height / thisgridSize; this.snake = [ { x: 10, y: 10 }, { x: 9, y: 10 }, { x: 8, y: 10 } ]; this.direction = Direction.RIGHT; this.nextDirection = Direction.RIGHT; this.score = 0; this.isGameOver = false; this.createFood(); this.setupInput(); this.startGame(); } private setupInput(): void { document.addEventListener('keydown', (e: KeyboardEvent) => { if (this.isGameOver) return; switch (e.key) { case 'ArrowUp': if (this.direction !== Direction.DOWN) { this.nextDirection = Direction.UP; } break; case 'ArrowDown': if (this.direction !== Direction.UP) { this.nextDirection = Direction.DOWN; } break; case 'ArrowLeft': if (this.direction !== Direction.RIGHT) { this.nextDirection = Direction.LEFT; } break; case 'ArrowRight': if (this.direction !== Direction.LEFT) { this.nextDirection = Direction.RIGHT; } break; } }); } private createFood(): void { let validPosition = false; while (!validPosition) { this.food = { x: Math.floor(Math.random() * this.gridWidth), y: Math.floor(Math.random() * this.gridHeight) }; validPosition = true; for (const segment of this.snake) { if (segment.x === this.food.x && segment.y === this.food.y) { validPosition = false; break; } } } } private startGame(): void { this.gameInterval = window.setInterval(() => { this.update(); this.draw(); }, 100); } private update(): void { if (this.isGameOver) return; this.direction = this.nextDirection; const head = { ...this.snake[0] }; switch (this.direction) { case Direction.UP: head.y -= 1; break; case Direction.DOWN: head.y += 1; break; case Direction.LEFT: head.x -= 1; break; case Direction.RIGHT: head.x += 1; break; } // Check wall collision if (head.x < 0 || head.x >= this.gridWidth || head.y < 0 || head.y >= this.gridHeight) { this.gameOver(); return; } // Check self collision for (const segment of this.snake) { if (head.x === segment.x && head.y === segment.y) { this.gameOver(); return; } } this.snake.unshift(head); // Check food collision if (head.x === this.food.x && head.y === this.food.y) { this.score += 10; this.scoreElement.textContent = this.score.toString(); this.createFood(); } else { this.snake.pop(); } } private draw(): void { // Clear canvas this.ctx.fillStyle = '#34495e'; this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); // Draw food this.ctx.fillStyle = '#e74c3c'; this.ctx.fillRect( this.food.x * this.gridSize, this.food.y * this.gridSize, this.gridSize - 2, this.gridSize - 2 ); // Draw snake this.ctx.fillStyle = '#2ecc71'; for (let i = 0; i < this.snake.length; i++) { const segment = this.snake[i]; // Make head a different color if (i === 0) { this.ctx.fillStyle = '#27ae60'; } else { this.ctx.fillStyle = '#2ecc71'; } this.ctx.fillRect( segment.x * this.gridSize, segment.y * this.gridSize, this.gridSize - 2, this.gridSize - 2 ); } if (this.isGameOver) { this.ctx.fillStyle = 'rgba(0, 0, 0, 0.7)'; this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); this.ctx.fillStyle = '#ecf0f1'; this.ctx.font = '30px Arial'; this.ctx.textAlign = 'center'; this.ctx.fillText('Game Over', this.canvas.width / 2, this.canvas.height / 2); this.ctx.font = '20px Arial'; this.ctx.fillText('Press F5 to restart', this.canvas.width / 2, this.canvas.height / 2 + 40); } } private gameOver(): void { this.isGameOver = true; if (this.gameInterval !== null) { clearInterval(this.gameInterval); this.gameInterval = null; } this.draw(); } } // Initialize game when DOM is ready document.addEventListener('DOMContentLoaded', () => { new SnakeGame(); }); ```