agent/users/jojo/project/snake_game/snake_game.html
2025-11-14 16:44:12 +08:00

341 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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>
body {
margin: 0;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #333;
font-family: Arial, sans-serif;
}
.game-container {
text-align: center;
}
canvas {
border: 2px solid #fff;
background-color: #111;
}
.info {
color: #fff;
margin: 10px 0;
font-size: 18px;
}
.controls {
margin-top: 20px;
}
button {
padding: 10px 20px;
font-size: 16px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin: 0 5px;
}
button:hover {
background-color: #45a049;
}
button:disabled {
background-color: #666;
cursor: not-allowed;
}
</style>
</head>
<body>
<div class="game-container">
<div class="info">
<div>得分: <span id="score">0</span></div>
<div>蛇长度: <span id="length">1</span></div>
<div>游戏状态: <span id="status">准备开始</span></div>
</div>
<canvas id="gameCanvas" width="600" height="600"></canvas>
<div class="controls">
<button id="startBtn">开始游戏</button>
<button id="pauseBtn" disabled>暂停</button>
<button id="resetBtn">重置</button>
</div>
</div>
<script>
class SnakeGame {
constructor() {
this.canvas = document.getElementById('gameCanvas');
this.ctx = this.canvas.getContext('2d');
this.gridSize = 20;
this.tileCount = this.canvas.width / this.gridSize;
this.reset();
this.setupEventListeners();
}
reset() {
this.snake = [
{x: 10, y: 10}
];
this.direction = {x: 0, y: 0};
this.apple = this.generateApple();
this.score = 0;
this.gameRunning = false;
this.gamePaused = false;
this.gameLoop = null;
this.speed = 100;
this.updateUI();
this.draw();
}
generateApple() {
let apple;
do {
apple = {
x: Math.floor(Math.random() * this.tileCount),
y: Math.floor(Math.random() * this.tileCount)
};
} while (this.snake.some(segment => segment.x === apple.x && segment.y === apple.y));
return apple;
}
setupEventListeners() {
document.getElementById('startBtn').addEventListener('click', () => this.start());
document.getElementById('pauseBtn').addEventListener('click', () => this.togglePause());
document.getElementById('resetBtn').addEventListener('click', () => this.reset());
}
start() {
if (!this.gameRunning) {
this.gameRunning = true;
this.gamePaused = false;
document.getElementById('startBtn').disabled = true;
document.getElementById('pauseBtn').disabled = false;
this.gameStep();
}
}
togglePause() {
if (this.gameRunning) {
this.gamePaused = !this.gamePaused;
document.getElementById('pauseBtn').textContent = this.gamePaused ? '继续' : '暂停';
if (!this.gamePaused) {
this.gameStep();
}
}
}
gameStep() {
if (!this.gameRunning || this.gamePaused) return;
this.moveSnake();
if (this.checkCollision()) {
this.gameOver();
return;
}
this.checkApple();
this.draw();
this.updateUI();
// 使用自动AI控制蛇的移动
this.autoMove();
setTimeout(() => this.gameStep(), this.speed);
}
autoMove() {
// 简单的AI朝着苹果方向移动
const head = this.snake[0];
const dx = this.apple.x - head.x;
const dy = this.apple.y - head.y;
// 计算最佳方向
let bestDirection = {x: 0, y: 0};
if (Math.abs(dx) > Math.abs(dy)) {
// 水平移动优先
bestDirection.x = dx > 0 ? 1 : -1;
bestDirection.y = 0;
} else {
// 垂直移动优先
bestDirection.x = 0;
bestDirection.y = dy > 0 ? 1 : -1;
}
// 检查是否会撞墙或撞到自己
const nextX = head.x + bestDirection.x;
const nextY = head.y + bestDirection.y;
if (this.isSafeMove(nextX, nextY)) {
this.direction = bestDirection;
} else {
// 如果直接路径不安全,寻找替代路径
this.findSafeDirection(head);
}
}
isSafeMove(x, y) {
// 检查是否会撞墙
if (x < 0 || x >= this.tileCount || y < 0 || y >= this.tileCount) {
return false;
}
// 检查是否会撞到自己(除了尾巴)
for (let i = 0; i < this.snake.length - 1; i++) {
if (this.snake[i].x === x && this.snake[i].y === y) {
return false;
}
}
return true;
}
findSafeDirection(head) {
// 尝试四个方向,找到安全的方向
const directions = [
{x: 1, y: 0}, // 右
{x: -1, y: 0}, // 左
{x: 0, y: 1}, // 下
{x: 0, y: -1} // 上
];
for (let dir of directions) {
const nextX = head.x + dir.x;
const nextY = head.y + dir.y;
if (this.isSafeMove(nextX, nextY)) {
this.direction = dir;
return;
}
}
// 如果没有安全方向,保持当前方向(游戏即将结束)
}
moveSnake() {
const head = {x: this.snake[0].x + this.direction.x, y: this.snake[0].y + this.direction.y};
this.snake.unshift(head);
// 如果没有吃到苹果,移除尾巴
if (head.x !== this.apple.x || head.y !== this.apple.y) {
this.snake.pop();
}
}
checkCollision() {
const head = this.snake[0];
// 撞墙检测
if (head.x < 0 || head.x >= this.tileCount || head.y < 0 || head.y >= this.tileCount) {
return true;
}
// 撞到自己检测
for (let i = 1; i < this.snake.length; i++) {
if (head.x === this.snake[i].x && head.y === this.snake[i].y) {
return true;
}
}
return false;
}
checkApple() {
const head = this.snake[0];
if (head.x === this.apple.x && head.y === this.apple.y) {
this.score += 10;
this.apple = this.generateApple();
// 检查是否填满整个地图
if (this.snake.length >= this.tileCount * this.tileCount) {
this.gameWin();
}
}
}
gameWin() {
this.gameRunning = false;
document.getElementById('status').textContent = '恭喜!蛇已铺满整个地图!';
document.getElementById('startBtn').disabled = false;
document.getElementById('pauseBtn').disabled = true;
}
gameOver() {
this.gameRunning = false;
document.getElementById('status').textContent = '游戏结束';
document.getElementById('startBtn').disabled = false;
document.getElementById('pauseBtn').disabled = true;
}
draw() {
// 清空画布
this.ctx.fillStyle = '#111';
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
// 画蛇
this.ctx.fillStyle = '#4CAF50';
for (let i = 0; i < this.snake.length; i++) {
const segment = this.snake[i];
this.ctx.fillRect(segment.x * this.gridSize, segment.y * this.gridSize, this.gridSize - 2, this.gridSize - 2);
// 蛇头用不同颜色
if (i === 0) {
this.ctx.fillStyle = '#81C784';
}
}
// 画苹果
this.ctx.fillStyle = '#FF5722';
this.ctx.fillRect(this.apple.x * this.gridSize, this.apple.y * this.gridSize, this.gridSize - 2, this.gridSize - 2);
// 画网格
this.ctx.strokeStyle = '#333';
this.ctx.lineWidth = 1;
for (let i = 0; i <= this.tileCount; i++) {
this.ctx.beginPath();
this.ctx.moveTo(i * this.gridSize, 0);
this.ctx.lineTo(i * this.gridSize, this.canvas.height);
this.ctx.stroke();
this.ctx.beginPath();
this.ctx.moveTo(0, i * this.gridSize);
this.ctx.lineTo(this.canvas.width, i * this.gridSize);
this.ctx.stroke();
}
}
updateUI() {
document.getElementById('score').textContent = this.score;
document.getElementById('length').textContent = this.snake.length;
if (this.gameRunning && !this.gamePaused) {
document.getElementById('status').textContent = '游戏进行中';
} else if (this.gamePaused) {
document.getElementById('status').textContent = '游戏暂停';
} else if (!this.gameRunning && this.snake.length > 1) {
document.getElementById('status').textContent = '游戏结束';
}
}
}
// 初始化游戏
window.addEventListener('DOMContentLoaded', () => {
new SnakeGame();
});
</script>
</body>
</html>