|
|
import gradio as gr |
|
|
|
|
|
|
|
|
snake_game_html = """ |
|
|
<style> |
|
|
#gameCanvas { |
|
|
background-color: #222; |
|
|
display: block; |
|
|
margin: 1em auto; |
|
|
border: 3px solid white; |
|
|
border-radius: 8px; |
|
|
} |
|
|
#instructions { |
|
|
text-align: center; |
|
|
color: white; |
|
|
font-family: Arial, sans-serif; |
|
|
margin-top: 0.5em; |
|
|
} |
|
|
</style> |
|
|
|
|
|
<canvas id="gameCanvas" width="400" height="400"></canvas> |
|
|
<div id="instructions">Use Arrow Keys to move the snake. Eat the red squares!</div> |
|
|
|
|
|
<script> |
|
|
const canvas = document.getElementById('gameCanvas'); |
|
|
const ctx = canvas.getContext('2d'); |
|
|
|
|
|
const grid = 20; |
|
|
let count = 0; |
|
|
let snake = { x: 160, y: 160, dx: grid, dy: 0, cells: [], maxCells: 4 }; |
|
|
let apple = { x: 320, y: 320 }; |
|
|
let score = 0; |
|
|
|
|
|
function getRandomInt(min, max) { |
|
|
return Math.floor(Math.random() * (max - min)) + min; |
|
|
} |
|
|
|
|
|
document.addEventListener('keydown', function(e) { |
|
|
if (e.key === 'ArrowLeft' && snake.dx === 0) { snake.dx = -grid; snake.dy = 0; } |
|
|
if (e.key === 'ArrowUp' && snake.dy === 0) { snake.dx = 0; snake.dy = -grid; } |
|
|
if (e.key === 'ArrowRight' && snake.dx === 0) { snake.dx = grid; snake.dy = 0; } |
|
|
if (e.key === 'ArrowDown' && snake.dy === 0) { snake.dx = 0; snake.dy = grid; } |
|
|
}); |
|
|
|
|
|
function gameLoop() { |
|
|
requestAnimationFrame(gameLoop); |
|
|
if (++count < 4) return; |
|
|
count = 0; |
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height); |
|
|
|
|
|
snake.x += snake.dx; |
|
|
snake.y += snake.dy; |
|
|
|
|
|
// Wrap snake position |
|
|
if (snake.x < 0) snake.x = canvas.width - grid; |
|
|
if (snake.x >= canvas.width) snake.x = 0; |
|
|
if (snake.y < 0) snake.y = canvas.height - grid; |
|
|
if (snake.y >= canvas.height) snake.y = 0; |
|
|
|
|
|
snake.cells.unshift({x: snake.x, y: snake.y}); |
|
|
if (snake.cells.length > snake.maxCells) snake.cells.pop(); |
|
|
|
|
|
// Draw apple |
|
|
ctx.fillStyle = 'red'; |
|
|
ctx.fillRect(apple.x, apple.y, grid-1, grid-1); |
|
|
|
|
|
// Draw snake |
|
|
ctx.fillStyle = 'lime'; |
|
|
snake.cells.forEach((cell, index) => { |
|
|
ctx.fillRect(cell.x, cell.y, grid-1, grid-1); |
|
|
|
|
|
// Check collision with apple |
|
|
if (cell.x === apple.x && cell.y === apple.y) { |
|
|
snake.maxCells++; |
|
|
score++; |
|
|
apple.x = getRandomInt(0, 20) * grid; |
|
|
apple.y = getRandomInt(0, 20) * grid; |
|
|
} |
|
|
|
|
|
// Check collision with self |
|
|
for (let i = index + 1; i < snake.cells.length; i++) { |
|
|
if (cell.x === snake.cells[i].x && cell.y === snake.cells[i].y) { |
|
|
alert("Game Over! Score: " + score); |
|
|
document.location.reload(); |
|
|
} |
|
|
} |
|
|
}); |
|
|
|
|
|
// Draw score |
|
|
ctx.fillStyle = 'white'; |
|
|
ctx.font = '16px Arial'; |
|
|
ctx.fillText('Score: ' + score, 10, 20); |
|
|
} |
|
|
|
|
|
requestAnimationFrame(gameLoop); |
|
|
</script> |
|
|
""" |
|
|
|
|
|
|
|
|
with gr.Blocks() as demo: |
|
|
gr.Markdown("## 🐍 Snake Game") |
|
|
gr.Markdown("Control the snake with arrow keys and eat the red apples to grow!") |
|
|
gr.HTML(snake_game_html) |
|
|
|
|
|
demo.launch() |
|
|
|