snake / index.html
bozhong's picture
增加排行榜TOP,表明 - Follow Up Deployment
ec00779 verified
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>贪吃蛇小游戏</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
/* 自定义样式 */
.game-container {
position: relative;
width: 100%;
max-width: 600px;
margin: 0 auto;
aspect-ratio: 1/1;
background-color: #f0f0f0;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.game-board {
display: grid;
grid-template-columns: repeat(20, 1fr);
grid-template-rows: repeat(20, 1fr);
width: 100%;
height: 100%;
}
.snake {
background-color: #4f46e5;
border-radius: 2px;
transition: all 0.1s ease;
}
.snake-head {
background-color: #3730a3;
border-radius: 4px;
}
.food {
background-color: #ef4444;
border-radius: 50%;
animation: pulse 1s infinite;
}
@keyframes pulse {
0% { transform: scale(0.9); }
50% { transform: scale(1.1); }
100% { transform: scale(0.9); }
}
.game-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: white;
z-index: 10;
}
.control-btn {
width: 60px;
height: 60px;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.2);
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
cursor: pointer;
transition: all 0.2s;
}
.control-btn:hover {
background-color: rgba(255, 255, 255, 0.3);
}
.control-btn:active {
transform: scale(0.95);
}
</style>
</head>
<body class="bg-gray-100 min-h-screen flex flex-col items-center justify-start p-4 overflow-hidden">
<div class="text-center mb-6">
<h1 class="text-3xl font-bold text-gray-800 mb-2">贪吃蛇小游戏</h1>
<div class="flex items-center justify-center space-x-4">
<div class="bg-white rounded-lg px-4 py-2 shadow">
<span class="text-gray-600">分数: </span>
<span id="score" class="font-bold text-indigo-600">0</span>
</div>
<div class="bg-white rounded-lg px-4 py-2 shadow">
<span class="text-gray-600">最高分: </span>
<span id="high-score" class="font-bold text-indigo-600">0</span>
</div>
</div>
</div>
<div class="game-container">
<div id="game-board" class="game-board"></div>
<div id="game-overlay" class="game-overlay hidden">
<h2 class="text-3xl font-bold mb-4">游戏结束!</h2>
<p class="text-xl mb-6">你的分数: <span id="final-score" class="font-bold">0</span></p>
<button id="restart-btn" class="bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-6 rounded-lg transition">
重新开始
</button>
</div>
</div>
<div class="mt-4 flex flex-wrap justify-center gap-4">
<button id="start-btn" class="bg-green-600 hover:bg-green-700 text-white font-bold py-2 px-6 rounded-lg transition">
开始游戏
</button>
<button id="pause-btn" class="bg-yellow-500 hover:bg-yellow-600 text-white font-bold py-2 px-6 rounded-lg transition hidden">
暂停
</button>
<div class="flex items-center bg-white rounded-lg px-4 py-2 shadow">
<label for="wall-mode" class="mr-2 text-gray-600">穿墙模式:</label>
<input type="checkbox" id="wall-mode" class="w-4 h-4 text-indigo-600 rounded">
</div>
</div>
<div class="mt-8 text-gray-600 text-sm">
<p>使用键盘方向键控制蛇的移动</p>
</div>
<script>
// 游戏变量
let snake = [];
let food = {};
let direction = 'right';
let nextDirection = 'right';
let gameInterval;
let gameSpeed = 150;
let score = 0;
let highScore = localStorage.getItem('snakeHighScore') || 0;
let isPaused = false;
let isGameOver = false;
let wallMode = false;
// DOM元素
const gameBoard = document.getElementById('game-board');
const scoreDisplay = document.getElementById('score');
const highScoreDisplay = document.getElementById('high-score');
const finalScoreDisplay = document.getElementById('final-score');
const gameOverlay = document.getElementById('game-overlay');
const startBtn = document.getElementById('start-btn');
const pauseBtn = document.getElementById('pause-btn');
const restartBtn = document.getElementById('restart-btn');
// 初始化游戏
function initGame() {
// 清空游戏板
gameBoard.innerHTML = '';
// 初始化蛇
snake = [
{x: 10, y: 10},
{x: 9, y: 10},
{x: 8, y: 10}
];
// 初始化方向
direction = 'right';
nextDirection = 'right';
// 生成食物
generateFood();
// 重置分数
score = 0;
scoreDisplay.textContent = score;
highScoreDisplay.textContent = highScore;
// 重置游戏状态
isPaused = false;
isGameOver = false;
// 隐藏游戏结束界面
gameOverlay.classList.add('hidden');
// 绘制游戏
drawGame();
}
// 绘制游戏
function drawGame() {
// 清空游戏板
gameBoard.innerHTML = '';
// 绘制蛇
snake.forEach((segment, index) => {
const snakeElement = document.createElement('div');
snakeElement.classList.add(index === 0 ? 'snake-head' : 'snake');
snakeElement.style.gridColumn = segment.x;
snakeElement.style.gridRow = segment.y;
gameBoard.appendChild(snakeElement);
});
// 绘制食物
const foodElement = document.createElement('div');
foodElement.classList.add('food');
foodElement.style.gridColumn = food.x;
foodElement.style.gridRow = food.y;
gameBoard.appendChild(foodElement);
}
// 生成食物
function generateFood() {
// 随机生成食物位置
food = {
x: Math.floor(Math.random() * 20) + 1,
y: Math.floor(Math.random() * 20) + 1
};
// 确保食物不会出现在蛇身上
for (let segment of snake) {
if (segment.x === food.x && segment.y === food.y) {
return generateFood();
}
}
}
// 游戏主循环
function gameLoop() {
if (isPaused || isGameOver) return;
// 更新方向
direction = nextDirection;
// 获取蛇头
const head = {...snake[0]};
// 根据方向移动蛇头
switch (direction) {
case 'up':
head.y -= 1;
break;
case 'down':
head.y += 1;
break;
case 'left':
head.x -= 1;
break;
case 'right':
head.x += 1;
break;
}
// 检查是否撞墙
if (!wallMode && (head.x < 1 || head.x > 20 || head.y < 1 || head.y > 20)) {
gameOver();
return;
}
// 穿墙处理
if (wallMode) {
if (head.x < 1) head.x = 20;
if (head.x > 20) head.x = 1;
if (head.y < 1) head.y = 20;
if (head.y > 20) head.y = 1;
}
// 检查是否撞到自己
for (let segment of snake) {
if (segment.x === head.x && segment.y === head.y) {
gameOver();
return;
}
}
// 移动蛇
snake.unshift(head);
// 检查是否吃到食物
if (head.x === food.x && head.y === food.y) {
// 增加分数
score += 10;
scoreDisplay.textContent = score;
// 更新最高分
if (score > highScore) {
highScore = score;
highScoreDisplay.textContent = highScore;
localStorage.setItem('snakeHighScore', highScore);
}
// 生成新食物
generateFood();
// 加快游戏速度
if (gameSpeed > 50 && score % 50 === 0) {
gameSpeed -= 5;
clearInterval(gameInterval);
gameInterval = setInterval(gameLoop, gameSpeed);
}
} else {
// 如果没有吃到食物,移除蛇尾
snake.pop();
}
// 重新绘制游戏
drawGame();
}
// 游戏结束
function gameOver() {
clearInterval(gameInterval);
isGameOver = true;
finalScoreDisplay.textContent = score;
gameOverlay.classList.remove('hidden');
}
// 开始游戏
function startGame() {
initGame();
gameInterval = setInterval(gameLoop, gameSpeed);
startBtn.classList.add('hidden');
pauseBtn.classList.remove('hidden');
}
// 暂停游戏
function togglePause() {
isPaused = !isPaused;
pauseBtn.textContent = isPaused ? '继续' : '暂停';
}
// 事件监听器
startBtn.addEventListener('click', startGame);
pauseBtn.addEventListener('click', togglePause);
restartBtn.addEventListener('click', startGame);
// 键盘控制
document.addEventListener('keydown', (e) => {
// 阻止方向键默认行为
if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', ' '].includes(e.key)) {
e.preventDefault();
}
switch (e.key) {
case 'ArrowUp':
if (direction !== 'down') nextDirection = 'up';
break;
case 'ArrowDown':
if (direction !== 'up') nextDirection = 'down';
break;
case 'ArrowLeft':
if (direction !== 'right') nextDirection = 'left';
break;
case 'ArrowRight':
if (direction !== 'left') nextDirection = 'right';
break;
case ' ':
if (!isGameOver) togglePause();
break;
}
});
// 穿墙模式切换
document.getElementById('wall-mode').addEventListener('change', (e) => {
wallMode = e.target.checked;
});
// 初始化显示
highScoreDisplay.textContent = highScore;
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=bozhong/awesome-about-me" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p><p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=bozhong/snake" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>