The sand accumulates to form a pagoda
- ✨ 写在前面
- ✨ 功能介绍
- ✨ 页面搭建
- ✨ 样式设置
- ✨ 逻辑部分
✨ 写在前面
上周我们实通过前端基础实现了俄罗斯方块游戏,今天还是继续按照我们原定的节奏来带领大家完成一个拼图游戏,功能也比较简单简单,也是想借助这样一个简单的功能,然后来帮助大家了解我们JavaScript在前端中的作用, 在前面的文章当中我们也提及到我们在本系列的专栏是循序渐进从简单到复杂的过程,这份专栏中我们会带领大家用前端实现翻卡片、飞机大战、弹珠游戏、贪吃蛇、井字游戏、拼图、连连看、扫雷等等有趣的小游戏,纯前端语言实现,都会陆续带给大家。欢迎大家订阅我们这份前端小游戏的专栏。订阅链接:https://blog.csdn.net/jhxl_/category_12261013.html
✨ 功能介绍
拼图游戏是一种经典的益智游戏,目标是将一张图片切割成多个小块,然后通过拖动小块的位置,重新排列它们以恢复原始图片。这个游戏测试你的观察能力、空间认知能力和逻辑思维能力。它不仅有助于放松大脑,还提供了娱乐和挑战。
功能介绍:
- 图片切割:游戏开始时,一张图片会被切割成多个小块,并以随机顺序排列在游戏区域内。
- 拖拽移动:通过鼠标点击小块并拖拽,可以移动小块的位置。
- 打乱拼图:点击"打乱拼图"按钮,可以重新随机排列拼图块的位置,增加挑战和乐趣。
- 恢复拼图:玩家的目标是将拼图块按照正确的顺序重新排列,恢复原始图片。
玩法说明:
- 游戏开始时,一张图片被切割成多个小块并随机排列在游戏区域内。
- 使用鼠标点击一个小块,然后拖拽它的位置,将其移动到空白位置或与其他小块交换位置。
- 继续移动其他小块,逐渐调整它们的位置,以恢复原始图片的完整性。
- 如果感到困惑或遇到难题,可以点击"打乱拼图"按钮重新排列小块,重新开始。
- 当所有小块都恰当地拼合在一起,恢复成原始图片时,游戏胜利。
- 在完成拼图后,会弹出恭喜信息的提示框,可以选择重新开始游戏或继续挑战。
这个拼图游戏结合了视觉和操作的挑战,你可以尝试不同的策略和方法来完成拼图,挑战自己的速度和技巧,享受拼图的乐趣和成就感。玩这个游戏,锻炼你的大脑,放松身心!
✨ 页面搭建
创建文件
首先呢我们创建我们的HTML文件,这里我就直接命名为 拼图.html
了,大家可以随意命名, 文件创建生成后我们通过编辑器打开,这里我用的是VScode, 然后初始化我们的代码结构,那在这里告诉大家一个快捷键,就是我们敲上我们英文的一个 !
我们敲击回车直接就会给我们生成基础版本的前端代码结构。
文档声明和编码设置: 在HTML文档的头部,使用<!DOCTYPE>声明HTML文档类型,确保浏览器以正确的方式渲染网页内容。同时,设置UTF-8编码,以确保浏览器能够正确地解析和显示中文字符。下面我就开始搭建我们的DOM结构了!
DOM结构搭建
以下是拼图游戏的基本DOM结构。玩家将在游戏板上看到拼图块,并通过点击按钮来打乱拼图块的位置。你可以根据这个基本结构来进一步实现拼图游戏的逻辑和功能。
<body>
<h2>图片切换拼图</h2>
<div id="puzzle-container">
<div id="puzzle-board"></div>
</div>
<button id="shuffle-btn">打乱拼图</button>
</body>
-
<h2>图片切换拼图</h2>
:这是一个标题,用于显示游戏的名称或标题,让玩家知道这是一个拼图游戏。 -
<div id="puzzle-container">
:这是一个容器,用于包含拼图游戏的主要内容。拼图块将显示在这个容器内。 -
<div id="puzzle-board"></div>
:这是一个用于显示拼图块的游戏板。在游戏开始时,拼图块会被放置在这个游戏板上。 -
<button id="shuffle-btn">打乱拼图</button>
:这是一个按钮,当点击它时,会触发打乱拼图的功能。点击这个按钮后,拼图块的位置将被重新随机排列,增加游戏的挑战性。
✨ 样式设置
我们看到了上面的的DOM已经搭建好了,但是页面什么都看不出来,下面我们简单的来配置一下样式吧,其实我们本专栏也是想带领大家掌握一些逻辑所以样式方面我们就一切从简;
<style>
#puzzle-container {
width: 300px;
height: 300px;
margin: 0 auto;
border: 2px solid #ccc;
position: relative;
overflow: hidden;
}
#puzzle-board {
width: 300px;
height: 300px;
position: absolute;
}
.puzzle-piece {
width: 100px;
height: 100px;
position: absolute;
background-size: 300px 300px;
border: 2px solid #fff;
transition: all 0.3s ease-in-out;
}
button {
display: block;
margin: 20px auto;
}
</style>
-
#puzzle-container
:这是拼图游戏容器的样式。它设置了容器的宽度和高度为300px,并使用margin: 0 auto
使其水平居中对齐。还设置了边框样式和相对定位,并使用overflow: hidden
属性隐藏超出容器大小的内容。 -
#puzzle-board
:这是拼图游戏板的样式。它设置了游戏板的宽度和高度为300px,并使用position: absolute
将其相对于父容器进行定位。 -
.puzzle-piece
:这是拼图块的样式。它设置了拼图块的宽度和高度为100px,并使用position: absolute
将其相对于父容器进行定位。background-size: 300px 300px
用于调整拼图块背景图的大小以适应游戏板。还设置了边框样式和过渡效果,使拼图块在移动时具有平滑的过渡效果。 -
button
:这是按钮的样式。display: block
使按钮以块级元素显示,margin: 20px auto
用于将按钮居中对齐。
以上是拼图游戏的基本CSS样式。通过这些样式,游戏容器、游戏板和拼图块将按照指定的样式进行布局和显示。你可以根据这个CSS代码继续完善拼图游戏的样式和外观。
✨ 逻辑部分
上面我们搭建了基本的样式,下面呢我们就通过js代码,实现我们游戏的功能吧,下面是对代码的简化解释:
好的,我将重点解释一些关键部分的代码。
-
document.addEventListener('DOMContentLoaded', () => { ... });
这段代码表示在文档加载完成后执行的函数,确保在操作DOM之前元素已经存在。 -
const puzzleContainer = document.getElementById('puzzle-container');
这行代码获取具有id
为 “puzzle-container” 的元素,并将其存储在puzzleContainer
变量中。这个容器元素是整个拼图游戏的外层容器。 -
const puzzleBoard = document.getElementById('puzzle-board');
这行代码获取具有id
为 “puzzle-board” 的元素,并将其存储在puzzleBoard
变量中。这个元素是用来放置拼图块的容器。 -
const shuffleButton = document.getElementById('shuffle-btn');
这行代码获取具有id
为 “shuffle-btn” 的元素,并将其存储在shuffleButton
变量中。这是一个按钮元素,用于触发打乱拼图的操作。 -
const imageSrc = 'https://img1.baidu.com/it/u=1960110688,1786190632&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281';
这是一个存储图片地址的变量,用于设置拼图块的背景图片。当然这里是我在网上随机找的图片,你也可以换成你想要的图片。 -
const rows = 3;
和const cols = 3;
这两行代码定义了拼图的行数和列数。 -
const pieces = [];
这行代码创建了一个空数组,用于存储拼图块的DOM元素。 -
let emptyPiece;
这是一个用于存储空拼图块的变量。 -
let isShuffling = false;
这是一个标志位变量,用于判断是否正在打乱拼图。 -
function createPuzzlePieces() { ... }
这是一个创建拼图块的函数。它根据行数和列数循环创建拼图块的DOM元素,并设置它们的样式、背景图片和位置。同时,为非空拼图块添加了点击事件监听器。 -
function movePiece(piece) { ... }
这是一个移动拼图块的函数。它根据点击的拼图块和空拼图块的位置关系,交换它们的位置,并更新它们的样式和数据集。 -
function checkWin() { ... }
这是一个检查是否完成拼图的函数。它遍历所有拼图块,根据其当前位置与正确位置进行比较,判断是否完成拼图。如果拼图完成,则显示恭喜的提示,并重新启用打乱按钮。 -
function shufflePuzzle() { ... }
这是一个打乱拼图的函数。它使用随机算法将拼图块进行打乱,将空拼图和其他拼图块进行交换,并计数打乱次数。在每次交换拼图块后,检查是否完成拼图,如果拼图已经完成,则显示完成提示,并重新启用打乱按钮。 -
createPuzzlePieces();
这行代码调用createPuzzlePieces()
函数,开始创建拼图块。 -
shuffleButton.addEventListener('click', shufflePuzzle);
这行代码为打乱按钮添加了点击事件监听器,点击按钮将触发shufflePuzzle()
函数,开始打乱拼图。
这些代码一起实现了一个基于DOM操作的拼图游戏。通过点击拼图块和打乱按钮,可以移动拼图块并打乱拼图,当拼图完成时会显示完成提示。
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>几何⚡️拼图</title>
<style>
#puzzle-container {
width: 300px;
height: 300px;
margin: 0 auto;
border: 2px solid #ccc;
position: relative;
overflow: hidden;
}
#puzzle-board {
width: 300px;
height: 300px;
position: absolute;
}
.puzzle-piece {
width: 100px;
height: 100px;
position: absolute;
background-size: 300px 300px;
border: 2px solid #fff;
transition: all 0.3s ease-in-out;
}
button {
display: block;
margin: 20px auto;
}
</style>
</head>
<body>
<h2>图片切换拼图</h2>
<div id="puzzle-container">
<div id="puzzle-board"></div>
</div>
<button id="shuffle-btn">打乱拼图</button>
</body>
<script>
document.addEventListener('DOMContentLoaded', () => {
const puzzleContainer = document.getElementById('puzzle-container');
const puzzleBoard = document.getElementById('puzzle-board');
const shuffleButton = document.getElementById('shuffle-btn');
const imageSrc = 'https://img1.baidu.com/it/u=1960110688,1786190632&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281'; // 替换为你的图片地址
const rows = 3;
const cols = 3;
const pieces = [];
let emptyPiece;
let isShuffling = false;
// 创建拼图块
function createPuzzlePieces() {
const pieceWidth = puzzleContainer.offsetWidth / cols;
const pieceHeight = puzzleContainer.offsetHeight / rows;
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
const piece = document.createElement('div');
piece.className = 'puzzle-piece';
piece.style.width = `${pieceWidth}px`;
piece.style.height = `${pieceHeight}px`;
piece.style.backgroundImage = `url(${imageSrc})`;
piece.style.backgroundPosition = `${-col * pieceWidth}px ${-row * pieceHeight}px`;
piece.style.top = `${row * pieceHeight}px`;
piece.style.left = `${col * pieceWidth}px`;
piece.dataset.row = row;
piece.dataset.col = col;
if (row === rows - 1 && col === cols - 1) {
emptyPiece = piece;
piece.classList.add('empty');
} else {
piece.addEventListener('click', () => {
if (!isShuffling) {
movePiece(piece);
}
});
}
puzzleBoard.appendChild(piece);
pieces.push(piece);
}
}
}
// 移动拼图块
function movePiece(piece) {
const emptyPieceRow = parseInt(emptyPiece.dataset.row);
const emptyPieceCol = parseInt(emptyPiece.dataset.col);
const pieceRow = parseInt(piece.dataset.row);
const pieceCol = parseInt(piece.dataset.col);
if (
(pieceRow === emptyPieceRow && Math.abs(pieceCol - emptyPieceCol) === 1) ||
(pieceCol === emptyPieceCol && Math.abs(pieceRow - emptyPieceRow) === 1)
) {
const tempRow = emptyPieceRow;
const tempCol = emptyPieceCol;
emptyPiece.style.top = `${pieceRow * piece.offsetHeight}px`;
emptyPiece.style.left = `${pieceCol * piece.offsetWidth}px`;
emptyPiece.dataset.row = pieceRow;
emptyPiece.dataset.col = pieceCol;
piece.style.top = `${tempRow * piece.offsetHeight}px`;
piece.style.left = `${tempCol * piece.offsetWidth}px`;
piece.dataset.row = tempRow;
piece.dataset.col = tempCol;
}
checkWin();
}
let isWin = false; // 添加标志位
// 检查是否完成拼图
function checkWin() {
let isPuzzleComplete = true;
for (let i = 0; i < pieces.length; i++) {
const piece = pieces[i];
const row = parseInt(piece.dataset.row);
const col = parseInt(piece.dataset.col);
if (row !== Math.floor(i / cols) || col !== i % cols) {
isPuzzleComplete = false;
break;
}
}
if (isPuzzleComplete && !isWin && !isShuffling) { // 添加条件判断
isWin = true; // 设置标志位为true
setTimeout(() => {
alert('恭喜!你完成了拼图!');
shuffleButton.disabled = false;
isWin = false; // 重置标志位为false
}, 200);
}
}
// 打乱拼图
function shufflePuzzle() {
isShuffling = true;
shuffleButton.disabled = true;
isWin = false; // 重置标志位为false
const shuffleCount = 100;
let count = 0;
const intervalId = setInterval(() => {
const randomIndex = Math.floor(Math.random() * pieces.length);
const randomPiece = pieces[randomIndex];
movePiece(randomPiece);
count++;
if (count >= shuffleCount) {
clearInterval(intervalId);
isShuffling = false;
shuffleButton.disabled = false;
}
}, 10);
}
createPuzzlePieces();
shuffleButton.addEventListener('click', shufflePuzzle);
});
</script>
</html>
本期推荐 查看详情
参与方式:本博客中进行评论即可,只要评论内容不被折叠都可以参与抽奖;
抽奖方式:程序自动拉取未折叠的评论随机抽取5位伙伴,每人最多可评论三次;
抽奖时间:2023-06-09 17:00
本期获奖者各送实体书《Spring Cloud 微服务快速上手》一本(包邮到家)
✨ 原创不易,还希望各位大佬支持一下 \textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下
👍 点赞,你的认可是我创作的动力! \textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向! \textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!