Vue如何实现扫雷
Vue 实现扫雷游戏的核心思路
扫雷游戏的核心逻辑包括生成雷区、处理点击事件、计算周围雷数以及递归展开空白区域。Vue 的响应式特性非常适合管理游戏状态和更新视图。
数据结构设计
使用二维数组表示雷区,每个格子包含以下属性:
{
isMine: false, // 是否是雷
revealed: false, // 是否已揭开
flagged: false, // 是否被标记
surrounding: 0 // 周围雷的数量
}
初始化雷区
在 Vue 的 data 或 setup 中初始化游戏状态:
data() {
return {
rows: 10,
cols: 10,
mines: 20,
board: [],
gameOver: false
}
}
生成雷区
在 created 或 mounted 钩子中调用初始化方法:
methods: {
initBoard() {
this.board = Array(this.rows).fill().map(() =>
Array(this.cols).fill().map(() => ({
isMine: false,
revealed: false,
flagged: false,
surrounding: 0
}))
);
this.placeMines();
this.calculateSurroundings();
}
}
随机布置地雷
placeMines() {
let minesPlaced = 0;
while (minesPlaced < this.mines) {
const row = Math.floor(Math.random() * this.rows);
const col = Math.floor(Math.random() * this.cols);
if (!this.board[row][col].isMine) {
this.board[row][col].isMine = true;
minesPlaced++;
}
}
}
计算周围雷数
calculateSurroundings() {
const directions = [
[-1, -1], [-1, 0], [-1, 1],
[0, -1], [0, 1],
[1, -1], [1, 0], [1, 1]
];
for (let row = 0; row < this.rows; row++) {
for (let col = 0; col < this.cols; col++) {
if (!this.board[row][col].isMine) {
let count = 0;
directions.forEach(([dx, dy]) => {
const newRow = row + dx;
const newCol = col + dy;
if (newRow >= 0 && newRow < this.rows &&
newCol >= 0 && newCol < this.cols &&
this.board[newRow][newCol].isMine) {
count++;
}
});
this.board[row][col].surrounding = count;
}
}
}
}
处理格子点击
revealCell(row, col) {
if (this.gameOver || this.board[row][col].revealed ||
this.board[row][col].flagged) return;
this.board[row][col].revealed = true;
if (this.board[row][col].isMine) {
this.gameOver = true;
this.revealAllMines();
return;
}
if (this.board[row][col].surrounding === 0) {
this.revealAdjacentCells(row, col);
}
}
递归展开空白区域
revealAdjacentCells(row, col) {
const directions = [
[-1, 0], [1, 0], [0, -1], [0, 1]
];
directions.forEach(([dx, dy]) => {
const newRow = row + dx;
const newCol = col + dy;
if (newRow >= 0 && newRow < this.rows &&
newCol >= 0 && newCol < this.cols &&
!this.board[newRow][newCol].revealed) {
this.revealCell(newRow, newCol);
}
});
}
标记雷格
toggleFlag(row, col) {
if (!this.board[row][col].revealed) {
this.board[row][col].flagged = !this.board[row][col].flagged;
}
}
模板渲染
<div class="minesweeper">
<div v-for="(row, rowIndex) in board" :key="rowIndex" class="row">
<div
v-for="(cell, colIndex) in row"
:key="colIndex"
class="cell"
:class="{
revealed: cell.revealed,
mine: cell.revealed && cell.isMine,
flagged: cell.flagged
}"
@click="revealCell(rowIndex, colIndex)"
@contextmenu.prevent="toggleFlag(rowIndex, colIndex)"
>
<span v-if="cell.revealed && !cell.isMine && cell.surrounding > 0">
{{ cell.surrounding }}
</span>
</div>
</div>
</div>
样式设计
.minesweeper {
display: inline-block;
border: 2px solid #333;
}
.row {
display: flex;
}
.cell {
width: 30px;
height: 30px;
border: 1px solid #999;
display: flex;
justify-content: center;
align-items: center;
background-color: #ccc;
cursor: pointer;
user-select: none;
}
.cell.revealed {
background-color: #fff;
}
.cell.mine {
background-color: #f00;
}
.cell.flagged::after {
content: "🚩";
}
游戏重置
添加重置按钮和方法:
<button @click="initBoard">New Game</button>
胜利条件判断
添加检查胜利的方法:
checkWin() {
for (let row = 0; row < this.rows; row++) {
for (let col = 0; col < this.cols; col++) {
if (!this.board[row][col].isMine && !this.board[row][col].revealed) {
return false;
}
}
}
this.gameOver = true;
return true;
}
在每次点击后调用 checkWin() 方法。
这个实现涵盖了扫雷游戏的基本功能,可以根据需要添加计时器、难度选择等进阶功能。Vue 的响应式系统会自动处理视图更新,使得游戏逻辑的实现更加简洁。







