- BC20280055's blog
扫雷
- @ 2025-11-7 22:19:00
Minesweeper 扫雷游戏
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Arial', Arial Black, Arial, sans-serif;
background-color: #D5EDFF;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.game-container {
text-align: center;
background-color: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
}
.header {
margin-bottom: 20px;
font-weight: 900;
font-size: 2em;
color: #333;
}
.header span {
vertical-align: middle;
margin-right: 10px;
}
.stats {
display: flex;
justify-content: space-between;
margin-bottom: 15px;
font-size: 1.2em;
font-weight: 900;
}
.board {
display: inline-grid;
gap: 2px;
background-color: #aaa;
padding: 5px;
border-radius: 5px;
user-select: none;
}
.tile {
width: 30px;
height: 30px;
background-color: #d3d3d3;
border: 2px solid;
border-top-color: #fff;
border-left-color: #fff;
border-right-color: #555;
border-bottom-color: #555;
display: flex;
justify-content: center;
align-items: center;
font-weight: 900;
font-size: 1.2em;
cursor: pointer;
transition: all 0.2s ease;
}
.tile:active {
border-top-color: #555;
border-left-color: #555;
border-right-color: #fff;
border-bottom-color: #fff;
}
.tile.revealed {
background-color: #c1c1c1;
border: 1px solid #999;
border-top-color: #aaa;
border-left-color: #aaa;
border-right-color: #ddd;
border-bottom-color: #ddd;
}
.tile.flagged::before {
content: "🚩";
font-size: 1.5em;
}
.tile.mine::before {
content: "💣";
font-size: 1.5em;
}
.tile[data-neighbor="1"] {
color: #0101FE;
}
.tile[data-neighbor="2"] {
color: #0A8209;
}
.tile[data-neighbor="3"] {
color: #e74c3c;
}
.tile[data-neighbor="4"] {
color: #9b59b6;
}
.tile[data-neighbor="5"] {
color: #e67e22;
}
.tile[data-neighbor="6"] {
color: #1abc9c;
}
.tile[data-neighbor="7"] {
color: #34495e;
}
.tile[data-neighbor="8"] {
color: #8e44ad;
}
.controls {
margin-top: 20px;
}
.reset-btn {
padding: 10px 20px;
font-family: 'Arial', Arial Black, Arial, sans-serif;
font-weight: 900;
font-size: 1.2em;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
.reset-btn:hover {
background-color: #45a049;
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 100;
}
.overlay-content {
background-color: white;
padding: 30px;
border-radius: 10px;
text-align: center;
font-family: 'Arial', Arial Black, Arial, sans-serif;
font-weight: 900;
font-size: 2em;
}
.overlay-content button {
margin-top: 15px;
padding: 10px 20px;
font-family: 'Arial', Arial Black, Arial, sans-serif;
font-weight: 900;
font-size: 1em;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
@media (max-width: 600px) {
.tile {
width: 15px;
height: 15px;
font-size: 0.8em;
}
.header {
font-size: 1.5em;
}
.stats {
font-size: 1em;
}
}
</style>
💣 Minesweeper
地雷: 15
标记: 0
New Game
<script>
// 游戏配置
const size = 10; // 网格大小
const bombFrequency = 0.15; // 炸弹频率
const totalCells = size * size;
const bombCount = Math.floor(totalCells * bombFrequency);
// 游戏状态
let board = [];
let bombs = [];
let revealed = 0;
let gameOver = false;
let gameWon = false;
let flags = 0;
// DOM元素
const boardElement = document.getElementById('board');
const resetBtn = document.getElementById('reset-btn');
const mineCountElement = document.getElementById('mine-count');
const flagCountElement = document.getElementById('flag-count');
// 初始化游戏
function initGame() {
// 重置游戏状态
board = [];
bombs = [];
revealed = 0;
gameOver = false;
gameWon = false;
flags = 0;
updateFlagCount();
mineCountElement.textContent = bombCount;
// 清空游戏板
boardElement.innerHTML = '';
boardElement.style.gridTemplateColumns = `repeat(${size}, 1fr)`;
// 创建游戏板
for (let row = 0; row < size; row++) {
board[row] = [];
for (let col = 0; col < size; col++) {
const tile = document.createElement('div');
tile.className = 'tile';
tile.setAttribute('data-tile', `${row},${col}`);
// 绑定点击事件
tile.addEventListener('click', () => handleTileClick(row, col));
tile.addEventListener('contextmenu', (e) => {
e.preventDefault();
handleRightClick(row, col);
});
boardElement.appendChild(tile);
board[row][col] = {
isBomb: false,
neighborCount: 0,
isRevealed: false,
isFlagged: false
};
}
}
// 随机放置炸弹
placeBombs();
// 计算邻居炸弹数
calculateNeighbors();
}
// 随机放置炸弹
function placeBombs() {
let bombsPlaced = 0;
while (bombsPlaced < bombCount) {
const row = Math.floor(Math.random() * size);
const col = Math.floor(Math.random() * size);
if (!board[row][col].isBomb) {
board[row][col].isBomb = true;
bombs.push({row, col});
bombsPlaced++;
}
}
}
// 计算每个方块的邻居炸弹数
function calculateNeighbors() {
const directions = [
[-1, -1], [-1, 0], [-1, 1],
[0, -1], [0, 1],
[1, -1], [1, 0], [1, 1]
];
for (let row = 0; row < size; row++) {
for (let col = 0; col < size; col++) {
if (!board[row][col].isBomb) {
let count = 0;
for (const [dr, dc] of directions) {
const newRow = row + dr;
const newCol = col + dc;
if (newRow >= 0 && newRow < size &&
newCol >= 0 && newCol < size &&
board[newRow][newCol].isBomb) {
count++;
}
}
board[row][col].neighborCount = count;
}
}
}
}
// 处理左键点击
function handleTileClick(row, col) {
if (gameOver || gameWon || board[row][col].isFlagged) return;
const tile = getTileElement(row, col);
if (board[row][col].isRevealed) return;
revealTile(row, col);
if (board[row][col].isBomb) {
// 游戏结束 - 踩到炸弹
tile.classList.add('mine');
gameOver = true;
revealAllBombs();
showGameOver(false);
} else if (board[row][col].neighborCount === 0) {
// 递归翻开相邻的空白区域
revealAdjacentEmptyTiles(row, col);
}
checkWin();
}
// 揭开方块
function revealTile(row, col) {
if (row < 0 || row >= size || col < 0 || col >= size) return;
if (board[row][col].isRevealed || board[row][col].isFlagged) return;
const tile = getTileElement(row, col);
board[row][col].isRevealed = true;
revealed++;
tile.classList.add('revealed');
if (board[row][col].isBomb) {
tile.classList.add('mine');
} else if (board[row][col].neighborCount > 0) {
tile.textContent = board[row][col].neighborCount;
tile.setAttribute('data-neighbor', board[row][col].neighborCount);
}
}
// 递归翻开相邻的空白区域
function revealAdjacentEmptyTiles(row, col) {
const directions = [
[-1, 0], [1, 0], [0, -1], [0, 1],
[-1, -1], [-1, 1], [1, -1], [1, 1]
];
for (const [dr, dc] of directions) {
const newRow = row + dr;
const newCol = col + dc;
if (newRow >= 0 && newRow < size &&
newCol >= 0 && newCol < size) {
if (!board[newRow][newCol].isRevealed && !board[newRow][newCol].isFlagged) {
revealTile(newRow, newCol);
if (board[newRow][newCol].neighborCount === 0) {
revealAdjacentEmptyTiles(newRow, newCol);
}
}
}
}
}
// 处理右键点击(标记/取消标记)
function handleRightClick(row, col) {
if (gameOver || gameWon || board[row][col].isRevealed) return;
const tile = getTileElement(row, col);
if (!board[row][col].isFlagged) {
// 添加标记
if (flags < bombCount) {
board[row][col].isFlagged = true;
tile.classList.add('flagged');
flags++;
}
} else {
// 移除标记
board[row][col].isFlagged = false;
tile.classList.remove('flagged');
flags--;
}
updateFlagCount();
}
// 获取方块DOM元素
function getTileElement(row, col) {
return document.querySelector(`[data-tile="${row},${col}"]`);
}
// 更新标记计数
function updateFlagCount() {
flagCountElement.textContent = flags;
}
// 检查是否获胜
function checkWin() {
const totalNonBombs = totalCells - bombCount;
if (revealed === totalNonBombs) {
gameWon = true;
gameOver = true;
showGameOver(true);
}
}
// 显示所有炸弹
function revealAllBombs() {
for (const bomb of bombs) {
const tile = getTileElement(bomb.row, bomb.col);
if (!board[bomb.row][bomb.col].isFlagged) {
tile.classList.add('revealed', 'mine');
}
}
}
// 显示游戏结束/胜利消息
function showGameOver(isWin) {
const overlay = document.createElement('div');
overlay.className = 'overlay';
const content = document.createElement('div');
content.className = 'overlay-content';
if (isWin) {
content.innerHTML = `
<div>🎉 胜利! 🎉</div>
<button onclick="this.parentElement.parentElement.remove(); initGame();">再玩一次</button>
`;
} else {
content.innerHTML = `
<div>💥 游戏结束! 💥</div>
<button onclick="this.parentElement.parentElement.remove(); initGame();">再玩一次</button>
`;
}
overlay.appendChild(content);
document.body.appendChild(overlay);
}
// 重置游戏
resetBtn.addEventListener('click', initGame);
// 初始化游戏
initGame();
</script>