以下がヘビゲームの実装例です。セキュリティ脆弱性の問題がないように注意しています。また、スタイルの設定は最小限にとどめ、必要最低限の機能に絞っています。
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hungry Snake</title>
<style>
body {
margin: 0;
}
canvas {
display: block;
border: solid black 1px;
}
</style>
</head>
<body>
<canvas></canvas>
<script>
// ゲームの定数
const CANVAS_SIZE = 400;
const BLOCK_SIZE = 20;
const INITIAL_SNAKE_LENGTH = 3;
const INTERVAL_MS = 100;
// ゲームオブジェクト
const canvas = document.querySelector('canvas');
canvas.width = CANVAS_SIZE;
canvas.height = CANVAS_SIZE;
const ctx = canvas.getContext('2d');
const snake = {
body: [],
dx: BLOCK_SIZE,
dy: 0,
isDead: false
};
const food = {
x: 0,
y: 0
};
let score = 0;
let intervalId;
let keyPressed = '';
// 初期化
function initialize() {
createSnake();
createFood();
draw();
intervalId = setInterval(moveSnake, INTERVAL_MS);
}
// スネークを生成
function createSnake() {
for (let i = 0; i < INITIAL_SNAKE_LENGTH; i++) {
snake.body.unshift({ x: (INITIAL_SNAKE_LENGTH - i) * BLOCK_SIZE, y: 0 });
}
}
// 餌を生成
function createFood() {
food.x = Math.floor(Math.random() * (CANVAS_SIZE / BLOCK_SIZE)) * BLOCK_SIZE;
food.y = Math.floor(Math.random() * (CANVAS_SIZE / BLOCK_SIZE)) * BLOCK_SIZE;
}
// スネークの描画
function drawSnake() {
ctx.fillStyle = 'green';
snake.body.forEach((block) => {
ctx.fillRect(block.x, block.y, BLOCK_SIZE, BLOCK_SIZE);
});
}
// 餌の描画
function drawFood() {
ctx.fillStyle = 'red';
ctx.fillRect(food.x, food.y, BLOCK_SIZE, BLOCK_SIZE);
}
// スコアの描画
function drawScore() {
ctx.fillStyle = 'black';
ctx.font = '20px sans-serif';
ctx.textAlign = 'center';
ctx.fillText(`Score: ${score}`, CANVAS_SIZE / 2, 30);
}
// ゲームオーバー時の描画
function drawGameOver() {
ctx.fillStyle = 'black';
ctx.font = '50px sans-serif';
ctx.textAlign = 'center';
ctx.fillText('Game Over', CANVAS_SIZE / 2, CANVAS_SIZE / 2);
}
// 描画
function draw() {
ctx.clearRect(0, 0, CANVAS_SIZE, CANVAS_SIZE);
drawSnake();
drawFood();
drawScore();
if (snake.isDead) {
drawGameOver();
}
}
// スネークを動かす
function moveSnake() {
if (snake.isDead) {
return;
}
const head = {
x: snake.body[0].x + snake.dx,
y: snake.body[0].y + snake.dy
};
// スネークが壁に当たった場合
if (head.x < 0 || head.x >= CANVAS_SIZE || head.y < 0 || head.y >= CANVAS_SIZE) {
snake.isDead = true;
clearInterval(intervalId);
draw();
return;
}
// スネークが自分に当たった場合
if (snake.body.some(block => block.x === head.x && block.y === head.y)) {
snake.isDead = true;
clearInterval(intervalId);
draw();
return;
}
// スネークが餌を食べた場合
if (head.x === food.x && head.y === food.y) {
score++;
createFood();
} else {
snake.body.pop();
}
snake.body.unshift(head);
draw();
}
// キーが押されたときの処理
function onKeyDown(event) {
switch (event.key) {
case 'ArrowUp':
if (snake.dy !== BLOCK_SIZE) {
snake.dx = 0;
snake.dy = -BLOCK_SIZE;
}
break;
case 'ArrowDown':
if (snake.dy !== -BLOCK_SIZE) {
snake.dx = 0;
snake.dy = BLOCK_SIZE;
}
break;
case 'ArrowLeft':
if (snake.dx !== BLOCK_SIZE) {
snake.dx = -BLOCK_SIZE;
snake.dy = 0;
}
break;
case 'ArrowRight':
if (snake.dx !== -BLOCK_SIZE) {
snake.dx = BLOCK_SIZE;
snake.dy = 0;
}
break;
default:
break;
}
}
// イベントリスナーの設定
document.addEventListener('keydown', onKeyDown);
// ゲームの開始
initialize();
</script>
</body>
</html>
```
ジョークとしては、「このスネークはとても空腹なので、たくさん餌を食べさせてあげてください。そうしないと、あなたが次の餌になってしまいます。」などがあります。