| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527 |
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>贪吃蛇小游戏</title>
- <style>
- * {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
- }
-
- body {
- display: flex;
- justify-content: center;
- align-items: center;
- min-height: 100vh;
- background: linear-gradient(135deg, #1a1a2e, #16213e);
- color: #fff;
- padding: 20px;
- }
-
- .game-container {
- max-width: 800px;
- width: 100%;
- background: rgba(255, 255, 255, 0.05);
- backdrop-filter: blur(10px);
- border-radius: 20px;
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
- overflow: hidden;
- padding: 25px;
- }
-
- header {
- text-align: center;
- margin-bottom: 20px;
- }
-
- h1 {
- font-size: 2.8rem;
- color: #ffd700;
- text-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
- margin-bottom: 5px;
- }
-
- .subtitle {
- font-size: 1.2rem;
- color: #e6e6e6;
- opacity: 0.8;
- }
-
- .game-info {
- display: flex;
- justify-content: space-between;
- align-items: center;
- background: rgba(0, 0, 0, 0.2);
- padding: 15px 25px;
- border-radius: 12px;
- margin-bottom: 20px;
- }
-
- .score-container {
- display: flex;
- align-items: center;
- gap: 10px;
- }
-
- .score-label {
- font-size: 1.2rem;
- font-weight: bold;
- }
-
- .score {
- font-size: 2rem;
- font-weight: bold;
- color: #ffd700;
- background: rgba(0, 0, 0, 0.3);
- padding: 5px 15px;
- border-radius: 10px;
- min-width: 80px;
- text-align: center;
- }
-
- .game-status {
- font-size: 1.2rem;
- font-weight: bold;
- padding: 8px 20px;
- border-radius: 50px;
- background: rgba(255, 255, 255, 0.1);
- }
-
- .game-status.playing {
- color: #4ade80;
- background: rgba(74, 222, 128, 0.15);
- }
-
- .game-status.paused {
- color: #fbbf24;
- background: rgba(251, 191, 36, 0.15);
- }
-
- .game-status.game-over {
- color: #f87171;
- background: rgba(248, 113, 113, 0.15);
- }
-
- .game-board {
- display: flex;
- justify-content: center;
- }
-
- canvas {
- background: rgba(0, 0, 0, 0.15);
- border-radius: 10px;
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
- }
-
- .controls {
- display: flex;
- justify-content: center;
- gap: 20px;
- margin: 25px 0;
- }
-
- button {
- padding: 12px 30px;
- font-size: 1.1rem;
- font-weight: bold;
- border: none;
- border-radius: 50px;
- cursor: pointer;
- transition: all 0.3s ease;
- outline: none;
- min-width: 120px;
- }
-
- #start-btn {
- background: linear-gradient(to right, #4ade80, #22c55e);
- color: white;
- box-shadow: 0 4px 10px rgba(74, 222, 128, 0.4);
- }
-
- #start-btn:hover {
- background: linear-gradient(to right, #22c55e, #16a34a);
- transform: translateY(-3px);
- box-shadow: 0 6px 15px rgba(74, 222, 128, 0.6);
- }
-
- #pause-btn {
- background: linear-gradient(to right, #fbbf24, #f59e0b);
- color: white;
- box-shadow: 0 4px 10px rgba(251, 191, 36, 0.4);
- }
-
- #pause-btn:hover {
- background: linear-gradient(to right, #f59e0b, #d97706);
- transform: translateY(-3px);
- box-shadow: 0 6px 15px rgba(251, 191, 36, 0.6);
- }
-
- #reset-btn {
- background: linear-gradient(to right, #60a5fa, #3b82f6);
- color: white;
- box-shadow: 0 4px 10px rgba(59, 130, 246, 0.4);
- }
-
- #reset-btn:hover {
- background: linear-gradient(to right, #3b82f6, #2563eb);
- transform: translateY(-3px);
- box-shadow: 0 6px 15px rgba(59, 130, 246, 0.6);
- }
-
- .instructions {
- background: rgba(255, 255, 255, 0.07);
- padding: 20px;
- border-radius: 12px;
- margin-top: 20px;
- }
-
- .instructions h2 {
- color: #ffd700;
- margin-bottom: 15px;
- font-size: 1.4rem;
- }
-
- .instructions ul {
- padding-left: 25px;
- }
-
- .instructions li {
- margin-bottom: 10px;
- line-height: 1.5;
- }
-
- .key {
- display: inline-block;
- background: rgba(255, 255, 255, 0.1);
- border: 1px solid rgba(255, 255, 255, 0.2);
- padding: 2px 8px;
- border-radius: 5px;
- font-family: monospace;
- }
-
- @media (max-width: 600px) {
- .game-info {
- flex-direction: column;
- gap: 15px;
- }
-
- .controls {
- flex-direction: column;
- align-items: center;
- }
-
- button {
- width: 100%;
- max-width: 300px;
- }
-
- canvas {
- width: 100%;
- max-width: 400px;
- height: auto;
- }
- }
- </style>
- </head>
- <body>
- <div class="game-container">
- <header>
- <h1>贪吃蛇小游戏</h1>
- <p class="subtitle">经典重现 - 控制小蛇吃食物,避免撞墙或撞到自己</p>
- </header>
-
- <div class="game-info">
- <div class="score-container">
- <span class="score-label">分数:</span>
- <div class="score">0</div>
- </div>
- <div class="game-status paused">游戏暂停</div>
- </div>
-
- <div class="game-board">
- <canvas id="gameCanvas" width="500" height="400"></canvas>
- </div>
-
- <div class="controls">
- <button id="start-btn">开始游戏</button>
- <button id="pause-btn">暂停游戏</button>
- <button id="reset-btn">重新开始</button>
- </div>
-
- <div class="instructions">
- <h2>游戏说明</h2>
- <ul>
- <li>使用 <span class="key">↑</span> <span class="key">←</span> <span class="key">↓</span> <span class="key">→</span> 方向键控制蛇的移动方向</li>
- <li>吃到红色食物可以增加分数并使蛇变长</li>
- <li>撞到墙壁或自己的身体会导致游戏结束</li>
- <li>游戏暂停时,按方向键可以继续游戏</li>
- <li>每吃一个食物得10分,吃得越多得分越高</li>
- </ul>
- </div>
- </div>
- <script>
- // 获取Canvas元素和上下文
- const canvas = document.getElementById('gameCanvas');
- const ctx = canvas.getContext('2d');
-
- // 游戏配置
- const gridSize = 20;
- const tileCount = canvas.width / gridSize;
- const fps = 8; // 游戏速度(帧率)
-
- // 游戏状态
- let snake = [];
- let food = {};
- let dx = gridSize; // x方向移动速度
- let dy = 0; // y方向移动速度
- let score = 0;
- let gameRunning = false;
- let gameInterval;
-
- // 获取DOM元素
- const scoreDisplay = document.querySelector('.score');
- const gameStatus = document.querySelector('.game-status');
- const startBtn = document.getElementById('start-btn');
- const pauseBtn = document.getElementById('pause-btn');
- const resetBtn = document.getElementById('reset-btn');
-
- // 初始化游戏
- function initGame() {
- // 初始化蛇(3个部分)
- snake = [
- {x: 7 * gridSize, y: 10 * gridSize},
- {x: 6 * gridSize, y: 10 * gridSize},
- {x: 5 * gridSize, y: 10 * gridSize}
- ];
-
- // 初始移动方向
- dx = gridSize;
- dy = 0;
-
- // 初始分数
- score = 0;
- updateScore();
-
- // 生成食物
- generateFood();
-
- // 绘制游戏
- drawGame();
-
- // 更新状态显示
- gameStatus.textContent = '游戏暂停';
- gameStatus.className = 'game-status paused';
- }
-
- // 生成食物
- function generateFood() {
- // 确保食物不会生成在蛇身上
- let foodOnSnake;
- do {
- foodOnSnake = false;
- food = {
- x: Math.floor(Math.random() * tileCount) * gridSize,
- y: Math.floor(Math.random() * tileCount) * gridSize
- };
-
- // 检查食物是否在蛇身上
- for (let segment of snake) {
- if (segment.x === food.x && segment.y === food.y) {
- foodOnSnake = true;
- break;
- }
- }
- } while (foodOnSnake);
- }
-
- // 绘制游戏
- function drawGame() {
- // 清除画布
- ctx.clearRect(0, 0, canvas.width, canvas.height);
-
- // 绘制网格背景
- ctx.fillStyle = 'rgba(30, 30, 46, 0.3)';
- for (let x = 0; x < canvas.width; x += gridSize) {
- for (let y = 0; y < canvas.height; y += gridSize) {
- ctx.fillRect(x, y, gridSize, gridSize);
- }
- }
-
- // 绘制蛇
- snake.forEach((segment, index) => {
- // 蛇头
- if (index === 0) {
- ctx.fillStyle = '#4ade80';
- ctx.fillRect(segment.x, segment.y, gridSize, gridSize);
-
- // 蛇头内部装饰
- ctx.fillStyle = '#166534';
- ctx.fillRect(segment.x + 4, segment.y + 4, gridSize - 8, gridSize - 8);
-
- // 眼睛
- ctx.fillStyle = '#000';
- ctx.fillRect(segment.x + 5, segment.y + 5, 4, 4);
- ctx.fillRect(segment.x + 11, segment.y + 5, 4, 4);
- }
- // 蛇身
- else {
- ctx.fillStyle = '#22c55e';
- ctx.fillRect(segment.x, segment.y, gridSize, gridSize);
-
- // 蛇身内部装饰
- ctx.fillStyle = '#14532d';
- ctx.fillRect(segment.x + 4, segment.y + 4, gridSize - 8, gridSize - 8);
- }
-
- // 边框
- ctx.strokeStyle = '#14532d';
- ctx.strokeRect(segment.x, segment.y, gridSize, gridSize);
- });
-
- // 绘制食物
- ctx.fillStyle = '#ef4444';
- ctx.beginPath();
- ctx.arc(food.x + gridSize/2, food.y + gridSize/2, gridSize/2, 0, Math.PI * 2);
- ctx.fill();
-
- // 食物内部装饰
- ctx.fillStyle = '#fecaca';
- ctx.beginPath();
- ctx.arc(food.x + gridSize/2, food.y + gridSize/2, gridSize/4, 0, Math.PI * 2);
- ctx.fill();
- }
-
- // 移动蛇
- function moveSnake() {
- // 创建新的蛇头
- const head = {x: snake[0].x + dx, y: snake[0].y + dy};
-
- // 检查是否撞墙
- if (head.x < 0 || head.x >= canvas.width || head.y < 0 || head.y >= canvas.height) {
- gameOver();
- return;
- }
-
- // 检查是否撞到自己
- for (let i = 0; i < snake.length; i++) {
- if (snake[i].x === head.x && snake[i].y === head.y) {
- gameOver();
- return;
- }
- }
-
- // 添加新的蛇头
- snake.unshift(head);
-
- // 检查是否吃到食物
- if (head.x === food.x && head.y === food.y) {
- // 增加分数
- score += 10;
- updateScore();
-
- // 生成新食物
- generateFood();
- } else {
- // 如果没吃到食物,移除蛇尾
- snake.pop();
- }
-
- // 重绘游戏
- drawGame();
- }
-
- // 更新分数显示
- function updateScore() {
- scoreDisplay.textContent = score;
- }
-
- // 游戏结束
- function gameOver() {
- clearInterval(gameInterval);
- gameRunning = false;
- gameStatus.textContent = '游戏结束!';
- gameStatus.className = 'game-status game-over';
- }
-
- // 开始游戏
- function startGame() {
- if (!gameRunning) {
- gameRunning = true;
- gameInterval = setInterval(moveSnake, 1000 / fps);
- gameStatus.textContent = '游戏中...';
- gameStatus.className = 'game-status playing';
- }
- }
-
- // 暂停游戏
- function pauseGame() {
- if (gameRunning) {
- clearInterval(gameInterval);
- gameRunning = false;
- gameStatus.textContent = '游戏暂停';
- gameStatus.className = 'game-status paused';
- }
- }
-
- // 重新开始游戏
- function resetGame() {
- pauseGame();
- initGame();
- }
-
- // 键盘控制
- document.addEventListener('keydown', (e) => {
- // 防止页面滚动
- if ([37, 38, 39, 40].includes(e.keyCode)) {
- e.preventDefault();
- }
-
- // 如果游戏暂停,按方向键开始游戏
- if (!gameRunning && [37, 38, 39, 40].includes(e.keyCode)) {
- startGame();
- }
-
- // 方向控制(不能直接反向)
- switch(e.keyCode) {
- case 37: // 左箭头
- if (dx === 0) {
- dx = -gridSize;
- dy = 0;
- }
- break;
- case 38: // 上箭头
- if (dy === 0) {
- dx = 0;
- dy = -gridSize;
- }
- break;
- case 39: // 右箭头
- if (dx === 0) {
- dx = gridSize;
- dy = 0;
- }
- break;
- case 40: // 下箭头
- if (dy === 0) {
- dx = 0;
- dy = gridSize;
- }
- break;
- }
- });
-
- // 按钮事件监听
- startBtn.addEventListener('click', startGame);
- pauseBtn.addEventListener('click', pauseGame);
- resetBtn.addEventListener('click', resetGame);
-
- // 初始化游戏
- initGame();
- </script>
- </body>
- </html>
|