大家好,我是Karin。
因為鐵人賽挑戰也快告一段落了,所以想藉由實作一個簡單的東西來當作是這系列的一個小成果。
好像是算完成了一個雛型了,但還是有很多可以優化跟加強的地方。
第三天:檢查遊戲結果與遊戲完成提示
目標:實現完成條件判斷,新增遊戲完成提示。
正文開始:
在圖片載入並切割圖片後,依序給予每個拼圖塊一個專屬的data-id,用來代表該拼圖塊的正確位置。
之後打亂拼圖塊,用data-current-id記錄該拼圖塊現在的位置,data-current-id會隨著使用者交換拼圖塊的動作而有所改變。
在每次使用者動作後(拼圖塊交換位置後),檢查每一個拼圖塊的 data-id 和 data-current-id 有無相同,若全部相同表示所有拼圖塊皆回到原本的位置上,顯示拼圖完成。
startTime = new Date().getTime();
取得當前的時間,返回的值是自 1970 年 1 月 1 日以來的毫秒數。
(使用Unix Epoch作為時間的參考點,這是計算機中默認的一個標準時間基點)
2.計算完成時間
取得遊戲結束時的時間(毫秒),計算耗時,並將毫秒轉換為秒。
const endTime = new Date().getTime();
const timeUsed = Math.floor((endTime - startTime) / 1000);
3.顯示耗時
setTimeout(() => {
alert(`恭喜你,拼圖完成了!\n用時:${timeUsed} 秒`);
}, 100);
這裡使用了 setTimeout(),將提示框的顯示稍微延遲 100 毫秒:
setTimeout():讓某件事情在一段時間後發生。
setTimeout(要執行的動作, 延遲的時間);
它像是一個鬧鐘,你告訴它過多久要做一件事,然後當時間到了,它就會自動執行你想做的事情。
時間單位一樣是毫秒。
因為在執行一些動作(如檢查拼圖完成)後,網頁需要一點時間來完成更新。使用 setTimeout 來確保在網頁更新完之後才彈出提示框,避免顯示上的衝突。
document.addEventListener('DOMContentLoaded', function() {
const imageUpload = document.getElementById('imageUpload');
const puzzleContainer = document.getElementById('puzzle-container');
let draggedTile = null; // 用來儲存當前被拖動的拼圖塊
let startTime;
// 監聽圖片上傳事件
imageUpload.addEventListener('change', function(event) {
const file = event.target.files[0]; // 取得上傳的圖片檔案
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
const img = new Image();
img.src = e.target.result;
img.onload = function() {
const rows = 3; // 固定為3行
const cols = 3; // 固定為3列
const containerWidth = puzzleContainer.clientWidth; // 取得容器的寬度
const containerHeight = puzzleContainer.clientHeight; // 取得容器的高度
// 根據容器大小計算每塊拼圖的寬高
const tileWidth = containerWidth / cols;
const tileHeight = containerHeight / rows;
// 清除之前的拼圖
puzzleContainer.innerHTML = '';
// 設置拼圖容器的行列數
puzzleContainer.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
puzzleContainer.style.gridTemplateRows = `repeat(${rows}, 1fr)`;
// 儲存圖片位置(背景位置)和正確的 ID
const positions = [];
for (let i = 0; i < rows * cols; i++) {
positions.push({
id: i, // 正確的位置 ID(原始順序)
backgroundPosition: `${-(i % cols) * tileWidth}px ${-Math.floor(i / cols) * tileHeight}px`
});
}
// 隨機打亂位置
const shuffledPositions = [...positions].sort(() => Math.random() - 0.5);
// 根據打亂後的順序生成拼圖塊
for (let i = 0; i < rows * cols; i++) {
const tile = document.createElement('div');
tile.classList.add('puzzle-tile');
tile.style.width = `${tileWidth}px`;
tile.style.height = `${tileHeight}px`;
tile.style.backgroundImage = `url(${img.src})`;
tile.style.backgroundSize = `${containerWidth}px ${containerHeight}px`;
tile.style.backgroundPosition = shuffledPositions[i].backgroundPosition;
tile.draggable = true; // 設置拼圖塊為可拖動
// 設置拼圖塊的正確位置 ID(保持原始圖片的順序)
tile.setAttribute('data-id', positions[i].id); // 正確的位置 ID
// 設置拼圖塊的當前位置 ID,初始化為打亂後的位置
tile.setAttribute('data-current-id', shuffledPositions[i].id); // 當前的位置 ID
// 拖動事件
tile.addEventListener('dragstart', function() {
draggedTile = tile; // 記錄當前被拖動的拼圖塊
});
// 設置拖放事件
tile.addEventListener('dragover', function(e) {
e.preventDefault(); // 允許放置
});
tile.addEventListener('drop', function() {
if (draggedTile !== tile) {
// 交換背景位置
const draggedBackgroundPosition = draggedTile.style.backgroundPosition;
draggedTile.style.backgroundPosition = tile.style.backgroundPosition;
tile.style.backgroundPosition = draggedBackgroundPosition;
// 交換 data-current-id
const draggedCurrentId = draggedTile.getAttribute('data-current-id');
const targetCurrentId = tile.getAttribute('data-current-id');
draggedTile.setAttribute('data-current-id', targetCurrentId);
tile.setAttribute('data-current-id', draggedCurrentId);
// 打印交換後的 ID,用於檢查
console.log(`拖動塊 ID: ${draggedTile.getAttribute('data-id')} => 當前 ID: ${draggedTile.getAttribute('data-current-id')}`);
console.log(`目標塊 ID: ${tile.getAttribute('data-id')} => 當前 ID: ${tile.getAttribute('data-current-id')}`);
}
// 檢查拼圖是否完成
checkPuzzleCompletion();
});
// 添加拼圖塊到容器
puzzleContainer.appendChild(tile);
}
// 開始計時
startTime = new Date().getTime();
};
};
reader.readAsDataURL(file);
}
});
// 檢查拼圖是否完成的函數
function checkPuzzleCompletion() {
const tiles = document.querySelectorAll('.puzzle-tile');
let isComplete = true;
tiles.forEach(tile => {
const correctId = tile.getAttribute('data-id'); // 正確的位置 ID
const currentId = tile.getAttribute('data-current-id'); // 當前的位置 ID
console.log(`檢查: Tile ID: ${correctId}, 當前 ID: ${currentId}`); // 打印檢查信息
if (correctId !== currentId) {
isComplete = false;
}
});
if (isComplete) {
const endTime = new Date().getTime();
const timeUsed = Math.floor((endTime - startTime) / 1000); // 以秒為單位
setTimeout(() => {
alert(`恭喜你,拼圖完成了!\n用時:${timeUsed} 秒`);
}, 100);
} else {
console.log("拼圖未完成"); //測試用
}
}
});
成功完成後跳出