Files
blackbird/static/public/games/game5.html
T
2026-07-23 11:30:26 +08:00

1134 lines
41 KiB
HTML

<!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 {
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
color: white;
overflow-x: hidden;
padding: 20px;
}
.container {
max-width: 600px;
width: 100%;
text-align: center;
}
h1 {
font-size: 3rem;
margin-bottom: 10px;
text-shadow: 0 0 10px #ff00ff, 0 0 20px #ff00ff;
letter-spacing: 2px;
background: linear-gradient(to right, #ff00ff, #00ffff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.subtitle {
font-size: 1.1rem;
margin-bottom: 15px;
color: #e0e0ff;
}
.game-info {
display: flex;
justify-content: space-between;
margin: 15px 0;
padding: 12px;
background: rgba(0, 0, 0, 0.5);
border-radius: 10px;
border: 1px solid #ff00ff;
flex-wrap: wrap;
}
.info-item {
font-size: 1.1rem;
font-weight: bold;
text-shadow: 0 0 5px #ff00ff;
margin: 5px 0;
}
.game-container {
position: relative;
margin: 15px auto;
border: 3px solid #ff00ff;
border-radius: 10px;
box-shadow: 0 0 20px #ff00ff, inset 0 0 20px rgba(255, 0, 255, 0.1);
overflow: visible; /* 改为visible让连击提示可以显示在外面 */
max-width: 500px;
background: rgba(0, 0, 0, 0.3);
padding: 15px;
}
.grid-container {
display: grid;
grid-template-columns: repeat(8, 1fr);
grid-template-rows: repeat(8, 1fr);
gap: 4px;
width: 100%;
aspect-ratio: 1/1;
background: rgba(0, 0, 0, 0.2);
border-radius: 6px;
padding: 8px;
position: relative;
}
.grid-cell {
background: rgba(255, 255, 255, 0.1);
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.2s ease;
}
.grid-cell:hover {
background: rgba(255, 255, 255, 0.2);
}
.gem {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
font-weight: bold;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s ease;
z-index: 10;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
user-select: none;
border: 2px solid rgba(255, 255, 255, 0.3);
}
.gem.selected {
transform: scale(0.9);
box-shadow: 0 0 15px #ffff00, 0 2px 5px rgba(0, 0, 0, 0.3);
border: 2px solid #ffff00;
}
/* 重新设计颜色,确保有明显区分 */
.gem.red {
background: linear-gradient(135deg, #ff416c, #ff4b2b);
color: white;
}
.gem.blue {
background: linear-gradient(135deg, #2196f3, #21cbf3);
color: white;
}
.gem.green {
background: linear-gradient(135deg, #00c853, #64dd17);
color: white;
}
.gem.yellow {
background: linear-gradient(135deg, #ffd600, #ffab00);
color: #333;
}
.gem.purple {
background: linear-gradient(135deg, #7b1fa2, #ba68c8);
color: white;
}
.gem.pink {
background: linear-gradient(135deg, #ec407a, #f48fb1);
color: white;
}
.gem.cyan {
background: linear-gradient(135deg, #00bcd4, #80deea);
color: #333;
}
.gem.matched {
animation: matchAnimation 0.5s ease-out;
}
@keyframes matchAnimation {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.2); opacity: 0.7; }
100% { transform: scale(0); opacity: 0; }
}
.gem.swapping {
animation: swapAnimation 0.3s ease;
}
@keyframes swapAnimation {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
.controls {
display: flex;
justify-content: center;
gap: 10px;
margin: 15px 0;
flex-wrap: wrap;
}
button {
background: linear-gradient(135deg, #ff00ff, #00ffff);
border: none;
padding: 10px 20px;
font-size: 1rem;
border-radius: 50px;
cursor: pointer;
color: #000;
font-weight: bold;
box-shadow: 0 0 15px rgba(255, 0, 255, 0.7);
transition: all 0.3s ease;
min-width: 120px;
}
button:hover {
transform: translateY(-3px);
box-shadow: 0 0 20px rgba(255, 0, 255, 0.9);
}
button:active {
transform: translateY(1px);
}
button:disabled {
background: #555;
color: #888;
box-shadow: none;
cursor: not-allowed;
}
.instructions {
margin-top: 20px;
padding: 15px;
background: rgba(0, 0, 0, 0.5);
border-radius: 10px;
border: 1px solid #ff00ff;
max-width: 500px;
}
.instructions h3 {
color: #ff00ff;
margin-bottom: 10px;
font-size: 1.3rem;
}
.instructions p {
margin: 8px 0;
color: #e0e0ff;
font-size: 0.95rem;
line-height: 1.4;
}
.game-over {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.9);
padding: 25px;
border-radius: 15px;
border: 2px solid #ff0000;
text-align: center;
box-shadow: 0 0 30px #ff0000;
z-index: 20;
display: none;
width: 85%;
max-width: 350px;
}
.game-over h2 {
font-size: 1.8rem;
color: #ff0000;
margin-bottom: 12px;
text-shadow: 0 0 10px #ff0000;
}
.game-over p {
font-size: 1.1rem;
margin: 8px 0;
}
.level-complete {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.9);
padding: 25px;
border-radius: 15px;
border: 2px solid #00ff00;
text-align: center;
box-shadow: 0 0 30px #00ff00;
z-index: 20;
display: none;
width: 85%;
max-width: 350px;
}
.level-complete h2 {
font-size: 1.8rem;
color: #00ff00;
margin-bottom: 12px;
text-shadow: 0 0 10px #00ff00;
}
.level-complete p {
font-size: 1.1rem;
margin: 8px 0;
}
.combo-display {
position: absolute;
top: -50px; /* 移到游戏区域上方 */
left: 50%;
transform: translateX(-50%);
font-size: 1.5rem;
font-weight: bold;
color: #ffff00;
text-shadow: 0 0 10px #ff0000, 0 0 20px #ff0000;
display: none;
animation: comboPulse 0.5s infinite alternate;
background: rgba(0, 0, 0, 0.7);
padding: 8px 16px;
border-radius: 25px;
border: 2px solid #ffff00;
z-index: 25;
white-space: nowrap;
}
@keyframes comboPulse {
from { transform: translateX(-50%) scale(1); }
to { transform: translateX(-50%) scale(1.1); }
}
.score-popup {
position: absolute;
font-size: 1.2rem;
font-weight: bold;
color: #ffff00;
text-shadow: 0 0 3px #000;
animation: scoreFloat 1s ease-out forwards;
pointer-events: none;
z-index: 15;
}
@keyframes scoreFloat {
0% { transform: translateY(0); opacity: 1; }
100% { transform: translateY(-30px); opacity: 0; }
}
@media (max-width: 600px) {
h1 {
font-size: 2.2rem;
}
.game-info {
flex-direction: column;
gap: 8px;
}
.controls {
flex-direction: column;
align-items: center;
gap: 8px;
}
button {
width: 100%;
max-width: 220px;
padding: 8px 15px;
}
.instructions {
margin-top: 15px;
padding: 12px;
}
.gem {
font-size: 1.2rem;
}
.grid-container {
grid-template-columns: repeat(8, 1fr);
grid-template-rows: repeat(8, 1fr);
gap: 3px;
padding: 6px;
}
.combo-display {
font-size: 1.3rem;
top: -45px;
padding: 6px 12px;
}
}
@media (max-width: 400px) {
body {
padding: 15px;
}
h1 {
font-size: 1.8rem;
}
.subtitle {
font-size: 0.95rem;
}
.game-container {
margin: 10px auto;
padding: 10px;
}
.controls {
margin: 10px 0;
}
button {
font-size: 0.9rem;
padding: 7px 12px;
}
.gem {
font-size: 1rem;
}
.combo-display {
font-size: 1.1rem;
top: -40px;
padding: 5px 10px;
}
}
</style>
</head>
<body>
<div class="container">
<h1>宝石迷阵</h1>
<p class="subtitle">交换宝石,三个或以上相同宝石连成一线即可消除!</p>
<div class="game-info">
<div class="info-item">分数: <span id="score">0</span></div>
<div class="info-item">目标: <span id="target">1000</span></div>
<div class="info-item">步数: <span id="moves">15</span></div>
<div class="info-item">连击: <span id="combo">0</span></div>
</div>
<div class="game-container">
<div class="combo-display" id="comboDisplay">连击 x<span id="comboCount">1</span>!</div>
<div class="grid-container" id="grid">
<!-- 网格将由JavaScript生成 -->
</div>
<div class="game-over" id="gameOver">
<h2>游戏结束</h2>
<p>你的最终分数: <span id="finalScore">0</span></p>
<p id="gameMessage">再试一次,创造新纪录!</p>
<button id="restartBtn">重新开始</button>
</div>
<div class="level-complete" id="levelComplete">
<h2>关卡完成!</h2>
<p>恭喜你完成了目标!</p>
<p>分数: <span id="levelScore">0</span></p>
<button id="nextLevelBtn">下一关</button>
</div>
</div>
<div class="controls">
<button id="startBtn">开始游戏</button>
<button id="hintBtn">提示</button>
<button id="shuffleBtn">重排</button>
</div>
<div class="instructions">
<h3>游戏说明</h3>
<p>点击选择一颗宝石,然后点击相邻的宝石进行交换</p>
<p>三个或更多相同颜色的宝石连成一线即可消除</p>
<p>连续消除可以产生连击,获得额外分数</p>
<p>在步数用完前达到目标分数即可过关</p>
<p>特殊组合可以产生爆炸效果,消除更多宝石!</p>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const gridContainer = document.getElementById('grid');
const startBtn = document.getElementById('startBtn');
const hintBtn = document.getElementById('hintBtn');
const shuffleBtn = document.getElementById('shuffleBtn');
const restartBtn = document.getElementById('restartBtn');
const nextLevelBtn = document.getElementById('nextLevelBtn');
const scoreEl = document.getElementById('score');
const targetEl = document.getElementById('target');
const movesEl = document.getElementById('moves');
const comboEl = document.getElementById('combo');
const gameOverEl = document.getElementById('gameOver');
const levelCompleteEl = document.getElementById('levelComplete');
const finalScoreEl = document.getElementById('finalScore');
const levelScoreEl = document.getElementById('levelScore');
const gameMessageEl = document.getElementById('gameMessage');
const comboDisplay = document.getElementById('comboDisplay');
const comboCount = document.getElementById('comboCount');
// 游戏配置 - 使用明显区分的颜色
const GRID_SIZE = 8;
const GEM_TYPES = ['red', 'blue', 'green', 'yellow', 'purple', 'pink', 'cyan'];
// 游戏状态
let game = {
grid: [],
score: 0,
target: 1000,
moves: 15,
level: 1,
combo: 0,
selectedGem: null,
isSwapping: false,
gameOver: false,
levelComplete: false
};
// 初始化游戏
function initGame() {
// 创建网格
game.grid = Array(GRID_SIZE).fill().map(() => Array(GRID_SIZE).fill(null));
game.score = 0;
game.moves = 15;
game.level = 1;
game.combo = 0;
game.selectedGem = null;
game.isSwapping = false;
game.gameOver = false;
game.levelComplete = false;
game.target = 1000;
// 生成网格HTML
createGridCells();
// 填充宝石
fillGrid();
updateUI();
gameOverEl.style.display = 'none';
levelCompleteEl.style.display = 'none';
comboDisplay.style.display = 'none';
// 渲染宝石
renderGems();
}
// 创建网格单元格
function createGridCells() {
gridContainer.innerHTML = '';
const containerWidth = gridContainer.offsetWidth;
const cellSize = (containerWidth - 24) / GRID_SIZE;
for (let i = 0; i < GRID_SIZE; i++) {
for (let j = 0; j < GRID_SIZE; j++) {
const cell = document.createElement('div');
cell.className = 'grid-cell';
cell.dataset.row = i;
cell.dataset.col = j;
cell.style.width = `${cellSize}px`;
cell.style.height = `${cellSize}px`;
// 添加点击事件到网格单元格
cell.addEventListener('click', handleCellClick);
gridContainer.appendChild(cell);
}
}
}
// 填充网格
function fillGrid() {
for (let i = 0; i < GRID_SIZE; i++) {
for (let j = 0; j < GRID_SIZE; j++) {
// 随机选择宝石类型,避免初始就有匹配
let gemType;
let attempts = 0;
do {
gemType = GEM_TYPES[Math.floor(Math.random() * GEM_TYPES.length)];
attempts++;
if (attempts > 20) break; // 防止无限循环
} while (hasInitialMatch(i, j, gemType));
game.grid[i][j] = {
type: gemType,
row: i,
col: j
};
}
}
// 检查并修复初始匹配
let matches = findMatches();
let attempts = 0;
while (matches.length > 0 && attempts < 50) {
// 重新填充有匹配的区域
matches.forEach(match => {
if (match.horizontal) {
for (let k = 0; k < 3; k++) {
const newType = GEM_TYPES[Math.floor(Math.random() * GEM_TYPES.length)];
game.grid[match.row][match.col + k].type = newType;
}
} else {
for (let k = 0; k < 3; k++) {
const newType = GEM_TYPES[Math.floor(Math.random() * GEM_TYPES.length)];
game.grid[match.row + k][match.col].type = newType;
}
}
});
matches = findMatches();
attempts++;
}
}
// 检查初始匹配
function hasInitialMatch(row, col, gemType) {
// 检查水平匹配
if (col >= 2 &&
game.grid[row][col-1]?.type === gemType &&
game.grid[row][col-2]?.type === gemType) {
return true;
}
// 检查垂直匹配
if (row >= 2 &&
game.grid[row-1][col]?.type === gemType &&
game.grid[row-2][col]?.type === gemType) {
return true;
}
return false;
}
// 渲染宝石
function renderGems() {
// 移除所有现有的宝石
const existingGems = document.querySelectorAll('.gem');
existingGems.forEach(gem => gem.remove());
// 获取网格容器的实际尺寸
const containerWidth = gridContainer.offsetWidth;
const containerHeight = gridContainer.offsetHeight;
// 计算每个格子的实际尺寸
const cellWidth = (containerWidth - 24) / GRID_SIZE;
const cellHeight = (containerHeight - 24) / GRID_SIZE;
// 添加新的宝石
for (let i = 0; i < GRID_SIZE; i++) {
for (let j = 0; j < GRID_SIZE; j++) {
const gem = game.grid[i][j];
if (gem) {
const gemElement = document.createElement('div');
gemElement.className = `gem ${gem.type}`;
gemElement.dataset.row = i;
gemElement.dataset.col = j;
// 使用像素精确定位
const left = 4 + j * (cellWidth + 4);
const top = 4 + i * (cellHeight + 4);
gemElement.style.left = `${left}px`;
gemElement.style.top = `${top}px`;
gemElement.style.width = `${cellWidth}px`;
gemElement.style.height = `${cellHeight}px`;
// 添加点击事件到宝石
gemElement.addEventListener('click', handleGemClick);
gridContainer.appendChild(gemElement);
}
}
}
}
// 处理单元格点击
function handleCellClick(e) {
if (game.gameOver || game.levelComplete || game.isSwapping) return;
const row = parseInt(e.target.dataset.row);
const col = parseInt(e.target.dataset.col);
// 找到对应的宝石元素
const gemElement = document.querySelector(`.gem[data-row="${row}"][data-col="${col}"]`);
if (gemElement) {
handleGemSelection(row, col, gemElement);
}
}
// 处理宝石点击
function handleGemClick(e) {
if (game.gameOver || game.levelComplete || game.isSwapping) return;
const row = parseInt(e.target.dataset.row);
const col = parseInt(e.target.dataset.col);
handleGemSelection(row, col, e.target);
}
// 处理宝石选择
function handleGemSelection(row, col, gemElement) {
// 如果没有选中的宝石,选中当前宝石
if (!game.selectedGem) {
game.selectedGem = { row, col };
gemElement.classList.add('selected');
return;
}
// 如果点击的是已选中的宝石,取消选择
if (game.selectedGem.row === row && game.selectedGem.col === col) {
game.selectedGem = null;
gemElement.classList.remove('selected');
return;
}
// 检查是否相邻
const rowDiff = Math.abs(game.selectedGem.row - row);
const colDiff = Math.abs(game.selectedGem.col - col);
if ((rowDiff === 1 && colDiff === 0) || (rowDiff === 0 && colDiff === 1)) {
// 交换宝石
swapGems(game.selectedGem.row, game.selectedGem.col, row, col);
} else {
// 选择新的宝石
document.querySelector('.gem.selected')?.classList.remove('selected');
game.selectedGem = { row, col };
gemElement.classList.add('selected');
}
}
// 交换宝石
function swapGems(row1, col1, row2, col2) {
game.isSwapping = true;
// 添加交换动画
const gem1 = document.querySelector(`.gem[data-row="${row1}"][data-col="${col1}"]`);
const gem2 = document.querySelector(`.gem[data-row="${row2}"][data-col="${col2}"]`);
if (gem1) gem1.classList.add('swapping');
if (gem2) gem2.classList.add('swapping');
// 交换网格中的数据
const temp = game.grid[row1][col1];
game.grid[row1][col1] = game.grid[row2][col2];
game.grid[row2][col2] = temp;
// 更新宝石位置
game.grid[row1][col1].row = row1;
game.grid[row1][col1].col = col1;
game.grid[row2][col2].row = row2;
game.grid[row2][col2].col = col2;
// 重新渲染
setTimeout(() => {
renderGems();
// 检查匹配
setTimeout(() => {
const matches = findMatches();
if (matches.length > 0) {
// 有匹配,处理消除
processMatches(matches);
} else {
// 没有匹配,交换回来
const temp = game.grid[row1][col1];
game.grid[row1][col1] = game.grid[row2][col2];
game.grid[row2][col2] = temp;
game.grid[row1][col1].row = row1;
game.grid[row1][col1].col = col1;
game.grid[row2][col2].row = row2;
game.grid[row2][col2].col = col2;
renderGems();
game.isSwapping = false;
}
// 清除选择
document.querySelector('.gem.selected')?.classList.remove('selected');
game.selectedGem = null;
}, 100);
}, 300);
}
// 查找匹配
function findMatches() {
const matches = [];
// 检查水平匹配
for (let i = 0; i < GRID_SIZE; i++) {
for (let j = 0; j < GRID_SIZE - 2; j++) {
const gem1 = game.grid[i][j];
const gem2 = game.grid[i][j+1];
const gem3 = game.grid[i][j+2];
if (gem1 && gem2 && gem3 &&
gem1.type === gem2.type && gem2.type === gem3.type) {
// 检查是否已经包含在匹配中
const isNewMatch = !matches.some(match =>
match.horizontal && match.row === i &&
(match.col === j || match.col === j-1 || match.col === j-2)
);
if (isNewMatch) {
matches.push({row: i, col: j, horizontal: true});
}
}
}
}
// 检查垂直匹配
for (let i = 0; i < GRID_SIZE - 2; i++) {
for (let j = 0; j < GRID_SIZE; j++) {
const gem1 = game.grid[i][j];
const gem2 = game.grid[i+1][j];
const gem3 = game.grid[i+2][j];
if (gem1 && gem2 && gem3 &&
gem1.type === gem2.type && gem2.type === gem3.type) {
// 检查是否已经包含在匹配中
const isNewMatch = !matches.some(match =>
!match.horizontal && match.col === j &&
(match.row === i || match.row === i-1 || match.row === i-2)
);
if (isNewMatch) {
matches.push({row: i, col: j, horizontal: false});
}
}
}
}
return matches;
}
// 处理匹配
function processMatches(matches) {
// 计算分数
const matchCount = matches.length;
const baseScore = matchCount * 100;
const comboBonus = game.combo * 50;
const totalScore = baseScore + comboBonus;
game.score += totalScore;
game.combo++;
game.moves--;
// 显示分数弹出效果
showScorePopup(totalScore);
// 显示连击 - 现在应该能正常显示了
if (game.combo > 1) {
comboCount.textContent = game.combo;
comboDisplay.style.display = 'block';
setTimeout(() => {
comboDisplay.style.display = 'none';
}, 1500); // 延长显示时间
}
// 标记匹配的宝石
const matchedGems = new Set();
matches.forEach(match => {
if (match.horizontal) {
for (let k = 0; k < 3; k++) {
matchedGems.add(`${match.row},${match.col + k}`);
}
} else {
for (let k = 0; k < 3; k++) {
matchedGems.add(`${match.row + k},${match.col}`);
}
}
});
// 添加匹配动画
matchedGems.forEach(pos => {
const [row, col] = pos.split(',').map(Number);
const gemElement = document.querySelector(`.gem[data-row="${row}"][data-col="${col}"]`);
if (gemElement) {
gemElement.classList.add('matched');
}
});
// 移除匹配的宝石并填充新宝石
setTimeout(() => {
// 移除匹配的宝石
matchedGems.forEach(pos => {
const [row, col] = pos.split(',').map(Number);
game.grid[row][col] = null;
});
// 下落宝石
dropGems();
// 填充空缺
fillEmptySpaces();
// 重新渲染
renderGems();
updateUI();
// 检查是否还有匹配
setTimeout(() => {
const newMatches = findMatches();
if (newMatches.length > 0) {
// 继续处理匹配
processMatches(newMatches);
} else {
game.isSwapping = false;
// 检查游戏状态
checkGameState();
}
}, 500);
}, 500);
}
// 显示分数弹出效果
function showScorePopup(score) {
const popup = document.createElement('div');
popup.className = 'score-popup';
popup.textContent = `+${score}`;
popup.style.left = '50%';
popup.style.top = '50%';
gridContainer.appendChild(popup);
setTimeout(() => {
popup.remove();
}, 1000);
}
// 宝石下落
function dropGems() {
for (let j = 0; j < GRID_SIZE; j++) {
let emptySpaces = 0;
for (let i = GRID_SIZE - 1; i >= 0; i--) {
if (game.grid[i][j] === null) {
emptySpaces++;
} else if (emptySpaces > 0) {
game.grid[i + emptySpaces][j] = game.grid[i][j];
game.grid[i][j] = null;
game.grid[i + emptySpaces][j].row = i + emptySpaces;
}
}
}
}
// 填充空缺
function fillEmptySpaces() {
for (let i = 0; i < GRID_SIZE; i++) {
for (let j = 0; j < GRID_SIZE; j++) {
if (game.grid[i][j] === null) {
const gemType = GEM_TYPES[Math.floor(Math.random() * GEM_TYPES.length)];
game.grid[i][j] = {
type: gemType,
row: i,
col: j
};
}
}
}
}
// 检查游戏状态
function checkGameState() {
if (game.moves <= 0) {
if (game.score >= game.target) {
// 关卡完成
game.levelComplete = true;
levelScoreEl.textContent = game.score;
levelCompleteEl.style.display = 'block';
} else {
// 游戏结束
game.gameOver = true;
finalScoreEl.textContent = game.score;
gameMessageEl.textContent = "步数用完了!再试一次吧!";
gameOverEl.style.display = 'block';
}
} else if (game.score >= game.target) {
// 关卡完成
game.levelComplete = true;
levelScoreEl.textContent = game.score;
levelCompleteEl.style.display = 'block';
}
}
// 提示功能
function showHint() {
// 找到所有可能的移动
const possibleMoves = [];
for (let i = 0; i < GRID_SIZE; i++) {
for (let j = 0; j < GRID_SIZE; j++) {
// 检查与右边宝石交换
if (j < GRID_SIZE - 1) {
// 交换
const temp = game.grid[i][j];
game.grid[i][j] = game.grid[i][j+1];
game.grid[i][j+1] = temp;
// 检查是否有匹配
const matches = findMatches();
// 交换回来
game.grid[i][j+1] = game.grid[i][j];
game.grid[i][j] = temp;
if (matches.length > 0) {
possibleMoves.push({row: i, col: j, direction: 'right'});
}
}
// 检查与下面宝石交换
if (i < GRID_SIZE - 1) {
// 交换
const temp = game.grid[i][j];
game.grid[i][j] = game.grid[i+1][j];
game.grid[i+1][j] = temp;
// 检查是否有匹配
const matches = findMatches();
// 交换回来
game.grid[i+1][j] = game.grid[i][j];
game.grid[i][j] = temp;
if (matches.length > 0) {
possibleMoves.push({row: i, col: j, direction: 'down'});
}
}
}
}
if (possibleMoves.length > 0) {
// 随机选择一个可能的移动
const move = possibleMoves[Math.floor(Math.random() * possibleMoves.length)];
const gem1 = document.querySelector(`.gem[data-row="${move.row}"][data-col="${move.col}"]`);
let gem2;
if (move.direction === 'right') {
gem2 = document.querySelector(`.gem[data-row="${move.row}"][data-col="${move.col + 1}"]`);
} else {
gem2 = document.querySelector(`.gem[data-row="${move.row + 1}"][data-col="${move.col}"]`);
}
if (gem1 && gem2) {
gem1.style.boxShadow = '0 0 15px #ffff00';
gem2.style.boxShadow = '0 0 15px #ffff00';
setTimeout(() => {
gem1.style.boxShadow = '';
gem2.style.boxShadow = '';
}, 2000);
}
} else {
alert('没有找到可匹配的移动!尝试重排宝石吧!');
}
}
// 重排宝石
function shuffleGems() {
if (game.moves <= 0) return;
// 收集所有宝石
const allGems = [];
for (let i = 0; i < GRID_SIZE; i++) {
for (let j = 0; j < GRID_SIZE; j++) {
allGems.push(game.grid[i][j]);
}
}
// 随机重排
for (let i = allGems.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[allGems[i], allGems[j]] = [allGems[j], allGems[i]];
}
// 重新分配位置
let index = 0;
for (let i = 0; i < GRID_SIZE; i++) {
for (let j = 0; j < GRID_SIZE; j++) {
game.grid[i][j] = allGems[index];
game.grid[i][j].row = i;
game.grid[i][j].col = j;
index++;
}
}
// 重新渲染
renderGems();
// 消耗一步
game.moves--;
updateUI();
// 检查游戏状态
checkGameState();
}
// 下一关
function nextLevel() {
game.level++;
game.score = 0;
game.moves = 15 + game.level * 2;
game.target = 1000 + game.level * 500;
game.combo = 0;
// 重新填充网格
fillGrid();
renderGems();
updateUI();
levelCompleteEl.style.display = 'none';
}
// 更新UI
function updateUI() {
scoreEl.textContent = game.score;
targetEl.textContent = game.target;
movesEl.textContent = game.moves;
comboEl.textContent = game.combo;
}
// 事件监听
startBtn.addEventListener('click', initGame);
hintBtn.addEventListener('click', showHint);
shuffleBtn.addEventListener('click', shuffleGems);
restartBtn.addEventListener('click', initGame);
nextLevelBtn.addEventListener('click', nextLevel);
// 窗口大小改变时重新渲染
window.addEventListener('resize', () => {
if (game.grid && game.grid.length > 0) {
createGridCells();
renderGems();
}
});
// 初始化游戏
initGame();
});
</script>
</body>
</html>