目前代碼沒有放到GitHub上,之後會放出鏈接 1.目錄結構: 2.index.html文件: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=de ...
目前代碼沒有放到GitHub上,之後會放出鏈接
1.目錄結構:
2.index.html文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div class="clearfix"> <!-- 拼圖游戲 --> <div style="float:left;" class="picture-puzzle"> </div> <!-- 對比圖片 --> <div style="float:right;"> <img src="./image/dog.jpg" alt=""> </div> </div> <script src="./js/index.js"></script> </body> </html>index.html
3.index.js文件:
// 游戲參數 var gameConfig = { width: 589, //整張圖片的寬度 height: 416, //整張圖片的高度 row: 3, //小方塊的行數 cols: 3, //小方塊的列數 imageurl: "./image/dog.jpg", //圖片的路徑 dom: document.getElementsByClassName("picture-puzzle")[0], //游戲容器的dom isOver: false, //游戲是否結束 minStep: 30,//打亂拼圖的最小步數 maxStep: 100//打亂拼圖的最大步數 // isHaveSolution: false //游戲是否有解 } gameConfig.pieceWidth = gameConfig.width / gameConfig.row; //每個小塊的寬度 gameConfig.pieceHeight = gameConfig.height / gameConfig.cols; //每個小塊的高度 var blocks = []; //存儲每個小塊的信息 //小方塊構造函數 function Block(row, cols) { // this.sequenceNumber; //方塊的編號從1到(row*cols)-1;空白格編號為0 this.width = gameConfig.pieceWidth; //寬 this.height = gameConfig.pieceHeight; //高 this.correctRow = row; //小方塊所在正確的行數,用來判斷方塊行數是否正確 this.correctCols = cols; //小方塊所在正確的列數,用來判斷方塊列數是否正確 this.row = row; //小方塊當前所在行數 this.cols = cols; //小方塊當前所在列數 this.isDisplay = false; //是否是空白塊:true.是;false:否; this.div = document.createElement("div"); this.div.style.width = gameConfig.pieceWidth + "px"; this.div.style.height = gameConfig.pieceHeight + "px"; this.div.style.background = `url("${gameConfig.imageurl}") -${this.correctCols * this.width}px -${this.correctRow * this.height}px`; this.div.style.border = "1px solid #fff"; this.div.style['box-sizing'] = "border-box"; this.div.style.position = "absolute"; this.show = function () { //展示小方塊顯示的位置 this.div.style.left = this.cols * gameConfig.pieceWidth + "px"; this.div.style.top = this.row * gameConfig.pieceHeight + "px"; } this.show(); if (row === gameConfig.row - 1 && cols === gameConfig.cols - 1) { //最後一方塊隱藏 this.div.style.display = "none"; this.isDisplay = true; //是否是空白塊:true.是;false:否; } gameConfig.dom.appendChild(this.div); this.isCorrect = function () { //判斷方塊當前位置的行列是否等於正確位置的行列 if (this.row === this.correctRow && this.cols === this.correctCols) { return true; } return false; } } //初始化游戲 function init() { //1.初始化游戲容器寬度 initGameDom(); //2.初始化每個小方塊基本信息 initBlocksArray(); //3.亂序拼圖可解的演算法沒有看懂,只能程式自動走100步 // while (!gameConfig.isHaveSolution) { randomSort(); // } //4.註冊點擊事件 registerEvent(); //初始化游戲容器 function initGameDom() { gameConfig.dom.style.width = gameConfig.width + "px"; gameConfig.dom.style.height = gameConfig.height + "px"; gameConfig.dom.style.border = "2px solid #ccc"; gameConfig.dom.style.position = "relative"; } //初始化小方塊數組信息 function initBlocksArray() { for (var i = 0; i < gameConfig.row; i++) { for (var j = 0; j < gameConfig.cols; j++) { // 每個小塊的基本信息 var block = new Block(i, j); blocks.push(block); } } // blocks.forEach(function (item, index) { // item.sequenceNumber = index + 1; // }); // blocks[gameConfig.row * gameConfig.cols - 1].sequenceNumber = 0; //最後一個空白塊編號為0 } //把小方塊打亂順序 function randomSort() { var step = getRandom(gameConfig.minStep, gameConfig.maxStep);//隨機在[30,100)區間里取出一個數,作為打亂拼圖的步數 console.log(step); //程式自走step步,將拼圖順序打亂 for (var i = 0; i < step; i++) { // 找到空白塊所在的行和列 var blankBlock = blocks.filter(function (item) { return item.isDisplay; }); for (var j = 0; j < blocks.length; j++) { //判斷是否可以交換,橫坐標相同則縱坐標相差1||縱坐標相同則橫坐標相差為1 if (blocks[j].row === blankBlock[0].row && Math.abs(blocks[j].cols - blankBlock[0].cols) === 1 || blocks[j].cols === blankBlock[0].cols && Math.abs(blocks[j].row - blankBlock[0].row) === 1) { exchangeBlocks(blocks[j], blankBlock[0]); continue; //交換一次後進入下個迴圈,保障交換次數為step次 } } } // for (var i = 0; i < (gameConfig.row * gameConfig.cols - 1); i++) { // //1.產生一個隨機數 // //2.將當前小方塊信息和隨機選中的小方塊信息互換,最後一個空白塊位置不變 // var index = getRandom(0, blocks.length - 2); // //交換數據 // exchangeBlocks(blocks[i], blocks[index]); // } blocks.forEach(function (item) { item.show(); }); //判斷拼圖是否有解 // haveSolution(); } //判斷亂序的拼圖是否有解 // function haveSolution() { // var count = 0; // //計算逆序列個數,逆序數:前面的編號大於後面的編號的個數 // for (var i = 0; i < blocks.length; i++) { // for (var j = i + 1; j < (blocks.length - 1 - i); j++) { // console.log(i, j, blocks[i].sequenceNumber); // if (blocks[i].sequenceNumber > blocks[j].sequenceNumber) { // count++; // } // } // } // console.log(count); // //計算空白塊編號為0所在的位置 // var blankBlock = gameConfig.row * gameConfig.cols - 1; // //奇偶性不同則無解 // gameConfig.isHaveSolution = (count % 2 != blankBlock % 2) ? false : true; // console.log(gameConfig.isHaveSolution); // } //為方塊註冊事件 function registerEvent() { //找到空白塊 var isDisplayBlock = blocks.find(function (item) { return item.isDisplay; }); blocks.forEach(function (item) { item.div.onclick = function () { if (gameConfig.isOver) { //游戲結束,則不在繼續以下操作 return; } //判斷是否可以交換,橫坐標相同則縱坐標相差1||縱坐標相同則橫坐標相差為1 if (item.row === isDisplayBlock.row && Math.abs(item.cols - isDisplayBlock.cols) === 1 || item.cols === isDisplayBlock.cols && Math.abs(item.row - isDisplayBlock.row) === 1) { exchangeBlocks(item, isDisplayBlock); } //游戲結束 isWin(); } }); } //交換兩個方塊的位置 function exchangeBlocks(b1, b2) { var temp = b1.row; b1.row = b2.row; b2.row = temp; var temp = b1.cols; b1.cols = b2.cols; b2.cols = temp; // var temp = b1.sequenceNumber; // b1.sequenceNumber = b2.sequenceNumber; // b2.sequenceNumber = temp; b1.show(); b2.show(); } //游戲結束 function isWin() { var wrongBlocks = blocks.filter(function (item) { //篩選出位置錯誤的方塊 return !item.isCorrect(); }); if (wrongBlocks.length === 0) { //所有方塊都在正確位置 gameConfig.isOver = true; //游戲結束 blocks.forEach(function (item) { item.div.style.display = "block"; item.div.style.border = "none"; }); } } //-------------通用函數----begin-----------// //返回一個[min,max)區間的隨機數 function getRandom(min, max) { return Math.floor(Math.random() * (max - min)) + min; } //-------------通用函數----end-----------// } init();index.js
代碼中都有簡單註釋,有什麼問題請在評論中提出,這裡只講解拼圖初始化時打亂拼圖順序所用的方法。
在網上找了好多拼圖的可解演算法,都沒有看太懂,若讀者知道或有實現方法,請賜教。
我這裡使用randomSort()方法,讓正確的順序自動走一定的步數去打亂拼圖的順序。
4.圖片文件
可以從網上隨意找一張圖片放到1中的image文件夾下,記得更改圖片名稱和路徑(imageurl),和圖片的width和height
上圖中是游戲的參數配置,可以自己修改下row,cols,minStep,maxStep看下效果
效果展示: