vue实现拼图游戏
实现思路
使用Vue实现拼图游戏的核心在于将图片分割为若干小块,随机打乱顺序后通过拖拽或点击交换位置,最终恢复原图。关键点包括图片分割、状态管理、交互逻辑和胜负判定。

核心代码结构
以下为基于Vue 3的示例代码框架(需安装vue-draggable-next库实现拖拽):
<template>
<div class="puzzle-container">
<div
v-for="(tile, index) in tiles"
:key="index"
class="tile"
:style="getTileStyle(tile)"
@click="handleTileClick(index)"
>
{{ tile.value }}
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const rows = 3;
const cols = 3;
const totalTiles = rows * cols;
// 初始化拼图块(示例用数字代替图片)
const tiles = ref(
Array.from({ length: totalTiles }, (_, i) => ({
value: i + 1,
originalPos: i,
currentPos: i
}))
);
// 打乱拼图
const shuffleTiles = () => {
tiles.value = [...tiles.value]
.sort(() => Math.random() - 0.5)
.map((tile, index) => ({ ...tile, currentPos: index }));
};
// 计算拼图块样式(实际项目替换为背景图定位)
const getTileStyle = (tile) => {
const row = Math.floor(tile.originalPos / cols);
const col = tile.originalPos % cols;
return {
width: `${100 / cols}%`,
height: `${100 / rows}%`,
transform: `translate(${col * 100}%, ${row * 100}%)`
};
};
// 处理点击交换
const handleTileClick = (clickedIndex) => {
const emptyIndex = tiles.value.findIndex(t => t.value === totalTiles);
if (isAdjacent(clickedIndex, emptyIndex)) {
swapTiles(clickedIndex, emptyIndex);
}
};
// 判断是否相邻
const isAdjacent = (a, b) => {
const rowA = Math.floor(a / cols);
const colA = a % cols;
const rowB = Math.floor(b / cols);
const colB = b % cols;
return Math.abs(rowA - rowB) + Math.abs(colA - colB) === 1;
};
// 交换位置
const swapTiles = (indexA, indexB) => {
[tiles.value[indexA], tiles.value[indexB]] =
[tiles.value[indexB], tiles.value[indexA]];
checkWin();
};
// 胜利判定
const checkWin = () => {
const isWin = tiles.value.every(
(tile, index) => tile.currentPos === tile.originalPos
);
if (isWin) alert('You Win!');
};
// 初始化打乱
shuffleTiles();
</script>
<style>
.puzzle-container {
width: 300px;
height: 300px;
position: relative;
border: 2px solid #333;
}
.tile {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
background-color: #eee;
cursor: pointer;
transition: transform 0.3s;
}
</style>
图片分割实现
实际项目中需将图片分割为网格:
- 使用
canvas将原图按行列数分割 - 为每个拼图块设置背景图及
background-position - 示例代码替换
getTileStyle方法:
const getTileStyle = (tile) => {
const row = Math.floor(tile.originalPos / cols);
const col = tile.originalPos % cols;
return {
backgroundImage: `url(your-image.jpg)`,
backgroundSize: `${cols * 100}% ${rows * 100}%`,
backgroundPosition: `${(col / (cols - 1)) * 100}% ${(row / (rows - 1)) * 100}%`
};
};
进阶优化方向
- 难度调节:动态修改
rows和cols参数 - 动画效果:添加移动过渡动画
- 本地存储:使用
localStorage保存游戏进度 - 空白块隐藏:将最后一块设置为透明
注意事项
- 移动有效性需验证(仅允许与空白块相邻的拼图移动)
- 随机打乱需确保有解(可通过逆序数校验)
- 响应式布局需考虑容器宽高比例与图片一致







