<!DOCTYPE html>
<html lang="zh-CN" data-theme="light">
<head>
<meta charset="UTF-8">
<title>智能扫雷(优化版)</title>
<style>
:root {
--bg-color: #f0f0f0;
--cell-color: #c0c0c0;
--text-color: #333;
--border-color: #808080;
--danger: #ff4444;
--safe: #4CAF50;
}
[data-theme="dark"] {
--bg-color: #2d2d2d;
--cell-color: #404040;
--text-color: #ddd;
--border-color: #666;
--danger: #d32f2f;
--safe: #388e3c;
}
body {
background: var(--bg-color);
color: var(--text-color);
transition: all 0.5s ease;
font-family: Arial, sans-serif;
}
.mode-select-container {
max-width: 500px;
margin: 2rem auto;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 15px rgba(0,0,0,0.2);
text-align: center;
}
.game-container {
max-width: 500px;
margin: 2rem auto;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 15px rgba(0,0,0,0.2);
}
.header {
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: space-between;
align-items: center;
padding: 10px;
background: var(--cell-color);
border-radius: 8px;
}
.grid {
display: grid;
gap: 2px;
margin-top: 1rem;
}
.cell {
aspect-ratio: 1;
background: var(--cell-color);
border: 2px solid var(--border-color);
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
user-select: none;
}
.cell:hover { transform: scale(1.1); }
.cell.revealed { background: var(--bg-color); }
.cell.mine { background: var(--danger) !important; }
.cell.flag { background: #ffecb3 !important; }
@keyframes reveal {
0% { transform: scale(0.8); opacity: 0; }
100% { transform: scale(1); opacity: 1; }
}
.theme-switch {
position: fixed;
top: 20px;
right: 20px;
font-size: 24px;
cursor: pointer;
transition: transform 0.3s;
}
.theme-switch:hover { transform: rotate(180deg); }
</style>
</head>
<body>
<div class="theme-switch" onclick="toggleTheme()">🌓</div>
<div class="mode-select-container" id="mode-select">
<h1>选择游戏模式</h1>
<button onclick="selectMode('default')">默认模式</button>
<button onclick="selectMode('custom')">自定义模式</button>
</div>
<div class="game-container" id="game-container" style="display: none;">
<button onclick="returnToModeSelect()">⬅️ 返回开始页面</button>
<div class="header">
<span id="mine-count">💣10</span>
<button onclick="initGame()">🔄 新游戏</button>
<button onclick="resetGame()">🔁 重来</button>
<span id="timer">⏱<span id="time">0</span></span>
<button id="swapBtn" onclick="swapClickMode()">↔️ 正常模式</button>
</div>
<div class="grid" id="grid"></div>
<div id="status"></div>
</div>
<div class="custom-mode-container" id="custom-mode-container" style="display: none;">
<h1>自定义模式</h1>
<label for="width">宽度:</label>
<input type="number" id="width" min="5" max="20" value="10">
<label for="height">高度:</label>
<input type="number" id="height" min="5" max="20" value="10">
<label for="mines">地雷数量:</label>
<input type="number" id="mines" min="1" max="100" value="10">
<button onclick="startCustomGame()">开始游戏</button>
<button onclick="returnToModeSelect()">⬅️ 返回开始页面</button>
</div>
<script>
let GRID_SIZE = 10;
let MINES_COUNT = 10;
let gameActive = true;
let timerInterval;
let cellsRevealed = 0;
let bestTime = localStorage.getItem('bestTime') || Infinity;
let isSwapped = false;
let remainingMines = MINES_COUNT;
let mineMap = [];
function selectMode(mode) {
document.getElementById('mode-select').style.display = 'none';
if (mode === 'default') {
GRID_SIZE = 10;
MINES_COUNT = 10;
document.getElementById('game-container').style.display = 'block';
initGame();
} else {
document.getElementById('custom-mode-container').style.display = 'block';
}
}
function startCustomGame() {
GRID_SIZE = parseInt(document.getElementById('width').value);
MINES_COUNT = parseInt(document.getElementById('mines').value);
document.getElementById('custom-mode-container').style.display = 'none';
document.getElementById('game-container').style.display = 'block';
initGame();
}
function returnToModeSelect() {
clearInterval(timerInterval);
document.getElementById('game-container').style.display = 'none';
document.getElementById('custom-mode-container').style.display = 'none';
document.getElementById('mode-select').style.display = 'block';
}
function initGame() {
clearInterval(timerInterval);
document.getElementById('time').textContent = '0';
document.getElementById('status').textContent = '';
gameActive = true;
cellsRevealed = 0;
remainingMines = MINES_COUNT;
document.getElementById('mine-count').textContent = `💣${remainingMines}`;
const grid = document.getElementById('grid');
grid.innerHTML = '';
grid.style.gridTemplateColumns = `repeat(${GRID_SIZE}, 1fr)`;
mineMap = createMineMap();
mineMap.forEach((row, i) => {
row.forEach((cell, j) => {
const div = document.createElement('div');
div.className = 'cell';
div.dataset.value = cell;
div.dataset.x = i;
div.dataset.y = j;
div.addEventListener('click', handleClick);
div.addEventListener('contextmenu', handleRightClick);
grid.appendChild(div);
});
});
let seconds = 0;
timerInterval = setInterval(() => {
if (gameActive) document.getElementById('time').textContent = ++seconds;
}, 1000);
}
function createMineMap() {
const map = Array(GRID_SIZE).fill().map(() => Array(GRID_SIZE).fill(0));
let mines = 0;
while (mines < MINES_COUNT) {
const x = Math.floor(Math.random() * GRID_SIZE);
const y = Math.floor(Math.random() * GRID_SIZE);
if (map[x][y] !== 'X') {
map[x][y] = 'X';
mines++;
}
}
for (let i = 0; i < GRID_SIZE; i++) {
for (let j = 0; j < GRID_SIZE; j++) {
if (map[i][j] === 'X') continue;
let count = 0;
for (let dx = -1; dx <= 1; dx++) {
for (let dy = -1; dy <= 1; dy++) {
const x = i + dx;
const y = j + dy;
if (x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE) {
if (map[x][y] === 'X') count++;
}
}
}
map[i][j] = count;
}
}
return map;
}
function handleClick(e) {
if (!gameActive) return;
const cell = e.target;
isSwapped ? handleRightClickAction(cell) : handleLeftClickAction(cell);
}
function handleRightClick(e) {
e.preventDefault();
if (!gameActive) return;
const cell = e.target;
isSwapped ? handleLeftClickAction(cell) : handleRightClickAction(cell);
}
function handleLeftClickAction(cell) {
const value = cell.dataset.value;
if (cell.classList.contains('flag')) return;
if (value === 'X') {
gameOver();
cell.classList.add('mine');
cell.textContent = '💥'; // 爆炸图标
} else {
revealCell(cell);
checkWinConditions(); // 检查胜利条件
}
}
function handleRightClickAction(cell) {
if (!cell.classList.contains('revealed')) {
const wasFlagged = cell.classList.contains('flag');
cell.classList.toggle('flag');
cell.textContent = cell.classList.contains('flag') ? '🚩' : '';
// 更新剩余地雷计数器
if (wasFlagged) {
remainingMines += 1;
} else {
remainingMines -= 1;
}
remainingMines = Math.max(0, Math.min(MINES_COUNT, remainingMines));
document.getElementById('mine-count').textContent = `💣${remainingMines}`;
checkWinConditions(); // 检查胜利条件
}
}
function revealCell(cell) {
if (cell.classList.contains('revealed')) return;
cell.classList.add('revealed');
cell.textContent = cell.dataset.value;
if (cell.dataset.value === '0') {
cell.textContent = '';
revealNeighbors(cell);
}
checkWinConditions(); // 检查胜利条件
}
function revealNeighbors(cell) {
const x = parseInt(cell.dataset.x);
const y = parseInt(cell.dataset.y);
for (let dx = -1; dx <= 1; dx++) {
for (let dy = -1; dy <= 1; dy++) {
const nx = x + dx;
const ny = y + dy;
const neighbor = document.querySelector(`[data-x="${nx}"][data-y="${ny}"]`);
if (neighbor && !neighbor.classList.contains('revealed')) {
revealCell(neighbor);
}
}
}
}
function checkWinConditions() {
// 检查所有非雷方块是否被揭开
const allNonMinesRevealed = Array.from(document.querySelectorAll('.cell'))
.filter(cell => cell.dataset.value !== 'X')
.every(cell => cell.classList.contains('revealed'));
// 如果所有非雷方块被揭开,判定为胜利
if (allNonMinesRevealed) {
gameActive = false;
clearInterval(timerInterval);
const time = parseInt(document.getElementById('time').textContent);
if (time < bestTime) {
bestTime = time;
localStorage.setItem('bestTime', bestTime);
}
document.getElementById('status').textContent = `🎉 胜利!恭喜你发现了所有的地雷! 最佳成绩:${bestTime}s`;
// 胜利时显示未爆炸的地雷图标
document.querySelectorAll('.cell').forEach(cell => {
if (cell.dataset.value === 'X') {
cell.textContent = '💣'; // 未爆炸的炸弹图标
cell.classList.add('revealed');
}
});
}
}
function gameOver() {
gameActive = false;
clearInterval(timerInterval);
document.querySelectorAll('.cell').forEach(cell => {
if (cell.dataset.value === 'X') {
cell.classList.add('mine');
cell.textContent = '💥'; // 爆炸图标
}
});
document.getElementById('status').textContent = '💥 踩到地雷了!游戏结束!';
}
function toggleTheme() {
document.body.dataset.theme = document.body.dataset.theme === 'light' ? 'dark' : 'light';
}
function swapClickMode() {
isSwapped = !isSwapped;
document.getElementById('swapBtn').textContent = isSwapped ? "↔️ 左键标记/右键点击(标记模式)" : "↔️ 正常模式";
}
function resetGame() {
clearInterval(timerInterval);
document.getElementById('time').textContent = '0';
document.getElementById('status').textContent = '';
gameActive = true;
cellsRevealed = 0;
remainingMines = MINES_COUNT;
document.getElementById('mine-count').textContent = `💣${remainingMines}`;
const grid = document.getElementById('grid');
Array.from(grid.children).forEach(cell => {
cell.classList.remove('revealed', 'mine', 'flag');
cell.textContent = '';
});
let seconds = 0;
timerInterval = setInterval(() => {
if (gameActive) document.getElementById('time').textContent = ++seconds;
}, 1000);
}
</script>
</body>
</html>
index.html
index.html