溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么使用js編寫實(shí)現(xiàn)拼圖游戲

發(fā)布時(shí)間:2022-07-13 10:13:27 來源:億速云 閱讀:265 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“怎么使用js編寫實(shí)現(xiàn)拼圖游戲”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“怎么使用js編寫實(shí)現(xiàn)拼圖游戲”吧!

目標(biāo)

使用原生js編寫一個(gè)拼圖游戲,我這里寫了兩種拼圖的方法。一種是拖拽拼圖,一種是經(jīng)典的九宮格拼圖,可以自定義參數(shù)設(shè)置游戲難度

先看看截圖效果

拖拽模式(拖拽圖片切換圖片)

怎么使用js編寫實(shí)現(xiàn)拼圖游戲

點(diǎn)擊模式(點(diǎn)擊圖片與空白區(qū)域切換位置)

怎么使用js編寫實(shí)現(xiàn)拼圖游戲

不多說,直接上代碼

css

#canvasBox{
        margin: 0 auto;
        position: fixed;
        border: 2px solid #f00;
        overflow: hidden;
    }
    .item{
        display: inline-block;
        border: 1px solid #f00;
        position: absolute;
        top: 0;
        left: 0;
        transition: 0.1s;
 }

html

<div >
        <button onclick="setGame('block', 'none')">拖拽模式</button>
        <button onclick="setGame('none', 'block')" >點(diǎn)擊模式</button>
    </div>
    
    <div id="canvasBox"></div>
<div id="canvasBox2"></div>

javascript

/*
             * @title JigsawGame 拼圖游戲
             * @params obj Object 游戲參數(shù)
             * {
             *     @param Id String 容器id
             *     @param imgUrl String 圖片路徑
             *     @param level Number 游戲難度 簡單:1 || 普通:2 || 困難:3
             *     @param gameType Number 游戲類型  拖動(dòng)版本:1 || 點(diǎn)擊版本:2
             * }
             * @author beideng
             */
            function JigsawGame(obj){

                // 初始化容器
                this.Id = document.getElementById(obj.Id);

                // 初始化圖片
                this.img = new Image();
                this.img.src = obj.imgUrl;

                // 容器最大寬度
                this.windowWidth = document.body.clientWidth;
                this.maxWidth = this.windowWidth > 750 ? 750 : (this.windowWidth * 0.9);

                // 設(shè)置容器寬高
                this.Id.style.width = this.maxWidth + "px";
                this.Id.style.height = this.maxWidth + "px";
                this.Id.style.left = (this.windowWidth - this.maxWidth)/2 + "px";
                this.Id.style.top = 50 + "px";

                // 獲取容器范圍
                this.boxOffsetY = parseFloat(this.Id.style.top);
                this.boxOffsetX = parseFloat( this.Id.style.left);

                // 關(guān)卡(簡單:1 || 普通:2 || 困難:3)
                if(obj.level == 1 || obj.level == 2 || obj.level == 3 ){
                    this.Level = obj.level;
                }else{
                    this.level = 1;    
                }

                // 難度
                var diffArr = [3, 4, 5];
                this.Diff= diffArr[this.Level-1];

                // canvas寬高
                this.cW = this.maxWidth/ this.Diff;
                this.cH = this.maxWidth/ this.Diff;

                // 記錄的小方塊個(gè)數(shù)
                this.number = 0;
                // 正確的數(shù)組
                this.numberArr = [];
                // 存儲小方塊的中心點(diǎn)坐標(biāo)
                this.centerXY = [];

                /*
                 * 獲取游戲類型
                 */
                this.gameType = obj.gameType || 1;

                // 記錄最后一個(gè)元素的標(biāo)記
                this.lastElement = {
                    sign: 0,
                    left: 0,
                    top: 0,
                    Id: obj.Id + 1
                };

                // 初始化
                this.Init();

            }

            /*
             * 操作方法 *
             */
            JigsawGame.prototype = {
                
                /*
                 * @method 初始化 
                 */
                Init: function(){

                    var that = this;

                    this.img.onload = function(){

                        // 格子寬高
                        var LevelW = that.img.width/that.Diff;
                        var LevelH = that.img.height/that.Diff;

                        for(var i = 0 ; i < that.Diff; i++){
                            for(var j = 0 ; j < that.Diff; j++){
                                // 初始化小方塊
                                that.initCube(i, j, LevelW, LevelH);
                            }
                        }

                        // 打亂小方塊
                        that.upsetElement();

                        // 游戲類型判斷
                        if(that.gameType == 1){
                            // 監(jiān)聽拖動(dòng)
                            that.Id.addEventListener("mousedown",function(event){
                                that.mouseDown(event);
                            }, false);
                        }else{
                            
                            // 獲取空白小方塊坐標(biāo)
                            that.getLastElement();

                            // 監(jiān)聽點(diǎn)擊
                            that.Id.addEventListener("click",function(event){
                                that.mouseClick(event);
                            }, false);
                        }

                    }

                },

                /*
                 * @method 初始化小方塊 
                 * @param i Number 循環(huán)值
                 * @param j Number 循環(huán)值
                 * @param j LevelW 小方塊寬
                 * @param j LevelH 小方塊高
                 */
                initCube: function(i, j, LevelW, LevelH){

                    // 創(chuàng)建一個(gè)小方塊
                    var item = document.createElement("div"),
                        cW = this.cW,
                        cH = this.cH;
                    
                    item.className = "item";
                    item.setAttribute("data-index", this.number);
                    item.style.width = cW + "px";
                    item.style.height = cH + "px";
                    item.style.left = i * cW + "px";
                    item.style.top = j * cH + "px";
                    item.innerHTML = "<canvas class='' width='"+ cW +"' height='"+ cH +"'></canvas>";
                    this.Id.appendChild(item);

                    var canvas = item.querySelector("canvas");
                    var ctx = canvas.getContext("2d");
                    
                    /*
                     * 當(dāng)游戲?yàn)辄c(diǎn)擊類型時(shí)
                     * 去掉最后一個(gè)小方塊里的圖片
                     * 且記錄當(dāng)前元素的坐標(biāo)以及編號
                     */ 
                    if(this.gameType != 1 && j == this.Diff-1 && i == this.Diff-1){
                        this.lastElement.sign = this.number;
                        item.id = this.lastElement.Id;

                    }else{
                        ctx.drawImage(this.img, i * LevelW, j * LevelH , LevelW, LevelH, 0 , 0, cW, cH)
                    }
                    
                    // 每添加一個(gè)就壓入一次到數(shù)組
                    this.numberArr.push({
                        x: i*cW +"px" ,
                        y: j*cH +"px"
                    });
                    this.number++;

                    // 壓入初始中心點(diǎn)
                    this.centerXY.push({
                        x: i*cW + cW / 2,
                        y: j*cH + cH / 2
                    });

                    
                },

                /*
                 * @method 懸停拖住小方塊
                 * @param event Object 鼠標(biāo)對象
                 */
                mouseDown: function(event){
                    console.log(event)

                     var event = event || window.event;

                     var that = this;

          var target = event.target || event.srcElement;

          // 保證拖動(dòng)的是想要的元素
          if( target.parentElement.className.toLowerCase() == "item"){
                        
                        var Element = target.parentElement;

                        // 存儲當(dāng)前元素的top,left
                        var thisTop = parseFloat( Element.style.top );
                        var thisLeft = parseFloat( Element.style.left );

                        // 獲取當(dāng)前點(diǎn)擊的位置
                        var pageX = event.pageX;
                        var pageY = event.pageY;
                        
                        // 拖動(dòng)
                        document.onmousemove = function(e){
                            console.log(e)
                            that.mouseMove(e, Element, thisTop, thisLeft, pageY, pageX);
                            
                            return false;
                        }
                        
                        // 松開
                        document.onmouseup = function(e){

                            that.mouseUp(e, Element, thisTop, thisLeft)
                            
                            // 釋放拖拽
                            document.onmousemove = null;
                            document.onmouseup = null;
                            return false;
                        }
          }

          return false;
                },

                /*
                 * @method 拖動(dòng)小方塊
                 * @param e Object 鼠標(biāo)對象
                 */
                mouseMove: function(e, Element, thisTop, thisLeft, pageY, pageX){
                     var pageX2 = e.pageX;
                    var pageY2 = e.pageY;
                    Element.style.top = thisTop + (pageY2 - pageY) + "px";
                    Element.style.left = thisLeft + (pageX2 - pageX) + "px";
                    Element.style.zIndex = 1000;
                },

                /*
                 * @method 松開小方塊
                 * @param e Object 鼠標(biāo)對象
                 */
                mouseUp: function(e, Element, thisTop, thisLeft){

                     var that = this,
                             cW = this.cW,
                            cH = this.cH;

                     // 檢測當(dāng)前拖動(dòng)替換目標(biāo)
                    var moveCenterX = parseFloat(Element.style.left) + cW / 2;
                    var moveCenterY = parseFloat(Element.style.top) + cH / 2;
                    var changeElementIndex = this.checkChangeElement(moveCenterX, moveCenterY);
                    var changeElement = this.Id.getElementsByClassName("item")[changeElementIndex];
            
                    // 限制拖拽范圍
                    // 當(dāng)松開的坐標(biāo)xy在容器范圍內(nèi)
                    if( e.pageX < this.boxOffsetX || e.pageX > (this.boxOffsetX + this.maxWidth) || e.pageY < this.boxOffsetY || e.pageY > (this.boxOffsetY + this.maxWidth) ){
                        console.log("釋放")

                        Element.style.top = thisTop  + "px";
                        Element.style.left = thisLeft + "px";
                        
                    }else{

                        // 判斷當(dāng)前元素是否離開了自己的格子
                        if( Element.getAttribute("data-index") == changeElement.getAttribute("data-index")){
                            Element.style.top = thisTop  + "px";
                            Element.style.left = thisLeft + "px";
                        }else{

                            // 進(jìn)行替換
                            Element.style.top = changeElement.style.top ;
                            Element.style.left = changeElement.style.left ;

                            changeElement.style.top = thisTop + "px";
                            changeElement.style.left = thisLeft + "px";
                            changeElement.style.zIndex = 1000; 

                            // 更新小方塊中心點(diǎn)
                    this.updateElement();
                        }

                    }

                    // 消除層級問題
                    setTimeout(function(){
                        Element.style.zIndex = 0;
                        changeElement.style.zIndex = 0; 
                        if(that.compareArray()){
                            alert("恭喜你,拼圖成功!");
                        }
                    }, 150);
                    
                    // 判斷拼圖完成
                    console.log(this.compareArray())
                    console.log(this.numberArr)

                },

                /*
                 * @method 檢測當(dāng)前拖動(dòng)替換目標(biāo)
                 * @param moveLeft Number 鼠標(biāo)移動(dòng)的x值
                 * @param moveTop Number 鼠標(biāo)移動(dòng)的y值
                 * @return minIndex Number 返回目標(biāo)對象下標(biāo)
                 * 通過三角函數(shù)檢測當(dāng)前拖動(dòng)對象中心點(diǎn)和其他所有對象中心點(diǎn)距離,離誰最近就和誰替換
                 */
                checkChangeElement: function(moveLeft, moveTop){

                    // 最小距離
                    var minDistance = null; 
                    // 最小距離替換目標(biāo)
                    var minIndex = null;

                    for(var i = 0 ; i < this.centerXY.length; i++){

                        var x = Math.abs( moveLeft - this.centerXY[i].x ); 
                        var y= Math.abs( moveTop - this.centerXY[i].y ); 
                        var val = Math.ceil(Math.sqrt( x * x +  y * y));
                        
                        // 初次判斷
                        if(minDistance == null){
                            minDistance = val;
                            minIndex = i;
                        } 
                        // 后續(xù)判斷
                        if(minDistance > val){
                            minDistance = val;
                            minIndex = i;
                        }

                    }
        
                    // 返回目標(biāo)對象下標(biāo)
                    return minIndex;
                },

                /*
                 * @method 更新小方塊中心點(diǎn)
                 */
                updateElement: function(){
                    var allElement = this.Id.getElementsByClassName("item"),
                            cW = this.cW,
                            cH = this.cH;
                    this.centerXY = [];

                    for(var i = 0 ; i < allElement.length; i++){
                        this.centerXY.push({
                            x: parseFloat(allElement[i].style.left) + cW / 2,
                            y: parseFloat(allElement[i].style.top) + cH / 2
                        });
                    }
                },

                /*
                 * @method 點(diǎn)擊小方塊
                 * @param event Object 鼠標(biāo)對象
                 * @ 1、點(diǎn)擊當(dāng)前非空白小方塊
                 * @ 2、獲取其坐標(biāo),并加減一個(gè)一個(gè)方塊寬度,用這個(gè)加減坐標(biāo)去檢索空白小方塊是否在目標(biāo)小方塊周邊
                 * @ 3、如果在,則替換這兩個(gè)小方塊的坐標(biāo)
                 */
                mouseClick: function(event){
                    console.log(event)

                     var event = event || window.event;

                     var that = this;

          var target = event.target || event.srcElement;

          // 保證拖動(dòng)的是想要的元素
          if( target.parentElement.className.toLowerCase() == "item"){
                        
                        var Element = target.parentElement;
                        
                        // 當(dāng)當(dāng)前點(diǎn)擊目標(biāo)為空白小方塊時(shí),終止函數(shù)
                        if(Element.getAttribute("data-index") == this.lastElement.sign){
                            return ;
                        }


                        // 存儲當(dāng)前元素的top,left
                        var thisTop = parseFloat( Element.style.top );
                        var thisLeft = parseFloat( Element.style.left );
                        
                        // 點(diǎn)擊檢測空白方塊是否在當(dāng)前對象周邊
                        if(this.mouseClickCheck(thisTop, thisLeft)){
                            console.log(222)
                            // 獲取空白元素
                            var lastElement = document.getElementById(this.lastElement.Id);
                            
                            // 替換這兩個(gè)元素的坐標(biāo)
                            Element.style.top = lastElement.style.top;
                            Element.style.left = lastElement.style.left;

                            lastElement.style.top = thisTop + "px";
                            lastElement.style.left = thisLeft + "px";

                            this.lastElement.left = thisLeft ;
                            this.lastElement.top = thisTop;
                        

                            // 消除層級問題
                            setTimeout(function(){
                                if(that.compareArray()){
                                    alert("恭喜你,拼圖成功!");
                                }
                            }, 150);
                            
                            // 判斷拼圖完成
                            console.log(this.compareArray())
                            console.log(this.numberArr)

                        }
                        
          }

          return false;
                },

                /*
                 * @method 點(diǎn)擊檢測空白方塊是否在當(dāng)前對象周邊
                 * @param thisTop Number 當(dāng)前點(diǎn)擊元素的top
                 * @param thisLeft NUmber 當(dāng)前點(diǎn)擊元素的left
                 * @return Boolean 是否在周邊
                 */
                mouseClickCheck: function(thisTop, thisLeft){

                    var cW = this.cW,
                            cH = this.cH;

                    if(thisTop == this.lastElement.top && (thisLeft - cH) == this.lastElement.left){
                        return true;
                    }

                    if(thisTop == this.lastElement.top && (thisLeft + cH) == this.lastElement.left){
                        return true;
                    }

                    if((thisTop - cW) == this.lastElement.top && thisLeft == this.lastElement.left){
                        return true;
                    }

                    if((thisTop + cW) == this.lastElement.top && thisLeft == this.lastElement.left){
                        return true;
                    }
    
                    return false;
                },

                /*
                 * @method 獲取空白元素left,right
                 */
                getLastElement: function(){

                    // 獲取空白元素
                    var lastElement = document.getElementById(this.lastElement.Id);
                    console.log(this.lastElement);
                    this.lastElement.left = parseFloat(lastElement.style.left) ;
                    this.lastElement.top = parseFloat(lastElement.style.top);
                },

                /*
                 * @method 打亂小方塊
                 * 以小方塊的個(gè)數(shù)為次數(shù),每次隨機(jī)抽取兩個(gè)小于小方塊的數(shù),然后替換兩個(gè)dom元素的定位坐標(biāo)
                 */
                upsetElement: function(){

                    for (var i = 0; i < this.number-1; i++) {

                        // 獲取兩個(gè)不相等的隨機(jī)值
                        var n1 = Math.floor(Math.random()*this.number);
                        var n2 = Math.floor(Math.random()*this.number);
                        do{
                            n2 = Math.floor(Math.random()*this.number);
                        }while(n1 == n2)

                        // 替換當(dāng)前的兩個(gè)小方塊的坐標(biāo)
                        var allElement = this.Id.getElementsByClassName("item");
                        var Top = allElement[n1].style.top ;
                        var Left = allElement[n1].style.left ;
                        
                        allElement[n1].style.top = allElement[n2].style.top ;
                        allElement[n1].style.left = allElement[n2].style.left ;
                        
                        allElement[n2].style.top = Top ;
                        allElement[n2].style.left = Left ;

                    }

                },

                /*
                 * @method 比較小方塊是否拼圖完成
                 * @return boolean
                 * 獲取切換小方塊后,獲取小方塊的序號并與正確排序數(shù)組進(jìn)行比較
                 */
                compareArray: function(){
                    // 獲取序號
                    var allElement = this.Id.getElementsByClassName("item");

                    for(var i = 0; i < this.number-1; i++){
                        // 比較序號
                        if( this.numberArr[i].x != allElement[i].style.left ||  this.numberArr[i].y != allElement[i].style.top ){
                            return false;
                        }
                    }
                    
                    return true;
                },

            }

            // 實(shí)例化一個(gè)對象
            var box = new JigsawGame({
                    Id: 'canvasBox',
                    imgUrl: '../image/lingtai.jpg',
                    level: 1,
                    gameType: 1
            });

            // 實(shí)例化一個(gè)對象
            var box2 = new JigsawGame({
                    Id: 'canvasBox2',
                    imgUrl: '../image/lingtai.jpg',
                    level: 1,
                    gameType: 2
            });

            function setGame(a, b){
                    document.getElementById("canvasBox").style.display = a;
                    document.getElementById("canvasBox2").style.display = b;
            }
            setGame("block", "none");

感謝各位的閱讀,以上就是“怎么使用js編寫實(shí)現(xiàn)拼圖游戲”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對怎么使用js編寫實(shí)現(xiàn)拼圖游戲這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

js
AI