JS之五子棋遊戲

mzs555557發表於2018-06-08
JS程式碼
var obox = document.getElementById("box"),
    arr = Array.apply(null,{length:20}),
    divWid = obox.offsetWidth / arr.length,
    oposi = obox.querySelector(".kuang .show"),
    pieces = obox.querySelector(".pieces"),
    movepie = obox.querySelector(".movepieces .move"),
    alertMove = obox.querySelector(".over"),
    alertClick = alertMove.querySelector("p"),
    boxdata = obox.querySelector(".data"),
    juedgArr = [{y:-1},{x:1,y:-1},{x:1},{x:1,y:1},{y:1},{x:-1,y:-1},{x:-1}],
    movepiece = null,                       //儲存跟隨滑鼠移動的棋子
    reserveCoor = null,                     //儲存移動時候最後的一個座標
    pieceCoor = {},                         //儲存棋子的座標
    resCoorOne = [],                        //儲存黑棋的座標    
    resCoorTwo = [],                        //儲存白棋的座標
    storeCoor = [],                         //儲存棋子用來回退
    coorColor = ["red","#000"],             //棋子顏色
    definultColor = null,
    definultJuedg = true,
    coorWid = 30/2,
    fadein = true,
    victory = 5;                            //設定多少棋連在一起就結束,預設是5


//初始化樣式
var fragment = document.createDocumentFragment();
arr.forEach(function(value,indexOne){
    arr.forEach(function(value,indexTwo){
        var odiv = document.createElement("div");
        odiv.classList.add("float");
        odiv.setAttribute("coordinate",indexOne+"-"+indexTwo);
        fragment.appendChild(odiv);
    });
});
boxdata.appendChild(fragment);

var boxInit = function(){
    movepie.style.backgroundColor = coorColor[0];

    //按x鍵悔棋
    document.addEventListener("keyup",docuKeyup);

    //obox的移動事件委託
    obox.addEventListener("mousemove",boxmove);

    //obox的點選實踐委託
    obox.addEventListener("click",boxclick);
};
boxInit();

//創造棋子
function createReserve(red,coor){
    coor = coor.split("-");
    var odiv = document.createElement("div");
    odiv.classList.add("pieces-coor");
    odiv.style.backgroundColor = red;
    odiv.style.top = coor[0] * divWid - coorWid+"px";
    odiv.style.left = coor[1] * divWid - coorWid+"px";
    pieces.appendChild(odiv);
    return odiv;
}

obox.addEventListener("mouseenter",function(){
    movepie.style.opacity = 1;
    oposi.style.opacity = 1;
});

obox.addEventListener("mouseleave",function(){
    movepie.style.opacity = 0;
    oposi.style.opacity = 0;
});

//判斷是否遊戲結束
function juedgVictory(bool){
    var arr = bool?resCoorOne:resCoorTwo;
    var someJuedg = arr.some(function(valueOne){
        return juedgArr.some(function(valueTwo){
            var str = valueOne.split("-"),
                coorX = parseInt(str[1]),
                coorY = parseInt(str[0]),
                x = valueTwo.x || 0,
                y = valueTwo.y || 0;
            return Array.apply(null,{length:victory-1}).every(function(value){
                coorX += x;coorY += y;
                return arr.indexOf(coorY+"-"+coorX) >=  0;
            });
        });
    });
    if(someJuedg){
        return overAlert();
    }
}

function overAlert(){
    //遊戲結束清除事件
    fadein = false;
    obox.removeEventListener("click",boxclick);
    obox.removeEventListener("mousemove",boxmove);
    document.removeEventListener("keyup",docuKeyup);
    alertMove.style.display = "block";
    setTimeout(function(){
        alertMove.style.opacity = 1;
    },100);
}
alertClick.addEventListener("click",function(){
    movepiece = null;                     
    reserveCoor = null;                     
    pieceCoor = {};                        
    resCoorOne = [];                           
    resCoorTwo = [];                       
    storeCoor = [];                               
    definultColor = null;
    definultJuedg = true;
    pieces.innerHTML = "";
    alertMove.style.opacity = 0;
    fadein = true;
    return boxInit();
});

alertMove.addEventListener("transitionend",function(){
    if(fadein)this.style.display = "none";
});

//document的鍵盤事件函式
function docuKeyup(e){
    if(e.keyCode === 88){
        if(!storeCoor.length)return;
        //儲存座標和棋子物件的回退
        var popmove = storeCoor.pop();
        for(var key in popmove){
            var one = resCoorOne.indexOf(key);
            var two = resCoorTwo.indexOf(key);
            //黑白棋子一起儲存的回退
            if(key in pieceCoor){
                //刪除棋子
                popmove[key].parentNode.removeChild(popmove[key]);
                delete pieceCoor[key];
            }
            //儲存黑白棋子座標進行回退
            if(one >= 0)resCoorOne.splice(one,1);
            if(two >= 0)resCoorTwo.splice(two,1);
            //顏色回退
            definultJuedg = !definultJuedg;
            movepie.style.backgroundColor = definultJuedg?coorColor[0]:coorColor[1];
        }
    }
}

//box的點選事件函式
function boxclick(e){
    e.cancelBubble = true;
    if(reserveCoor){
        if(definultJuedg){
            definultColor = coorColor[0];
            resCoorOne.push(reserveCoor);
        }else{
            definultColor = coorColor[1];
            resCoorTwo.push(reserveCoor);
        }
        pieceCoor[reserveCoor] = true;
        storeCoor.push({[reserveCoor]:createReserve(definultColor,reserveCoor)});
        definultJuedg = !definultJuedg;
        movepie.style.backgroundColor = definultJuedg?coorColor[0]:coorColor[1];
        //判斷是否勝利
        return juedgVictory(!definultJuedg);
    }
}

//obox的mousemove事件函式
function boxmove(e){
    var target = e.target.getAttribute("coordinate");
        if(!target)return;  
    var moveXY = target.split("-"),
        mX = e.pageX - obox.offsetLeft,
        mY = e.pageY - obox.offsetTop,
        moveOne = parseInt(moveXY[0]),
        moveTwo = parseInt(moveXY[1]),
        fourCoor = [[moveOne,moveTwo],[moveOne,moveTwo+1],[moveOne+1,moveTwo],[moveOne+1,moveTwo+1]];
    
        movepie.style.left = mX - (movepie.offsetWidth/2)+"px";
        movepie.style.top = mY- (movepie.offsetWidth/2)+"px";

    //用勾股定義選擇靠的最近的一個座標
    var minXY = fourCoor.map(function(value,index){
        var moY = Math.abs(mY - value[0] * divWid),
            moX = Math.abs(mX - value[1] * divWid);
        return [Math.sqrt(moY * moY + moX * moX),value];
    }).filter(function(value){
        //過濾掉座標上以有棋子的
        if(!(pieceCoor[value[1].join("-")])){
            return value;
        }
    });
    if(!minXY.length)return;
    minXY = minXY.sort(function(a,b){
        return a[0] - b[0];
    })[0][1];
    reserveCoor = minXY.join("-");
    var oposiLate = minXY.map(function(value,index){
        return (value * divWid) - (oposi.offsetWidth / 2);
    });
    oposi.style.transform = "translate("+oposiLate[1]+"px,"+oposiLate[0]+"px)";
}

HTML程式碼
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="Author" content="Fly">
        <title>Title</title>
        <style>
            *{ margin: 0; padding: 0; font-family:Microsoft yahei,serif;}
            li{ list-style:none;}
            #box{
                position: relative;
                width: 800px;
                height: 800px;
                margin: 0 auto;
            }
            #box .data,.kuang,.piecess,.movepieces{
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
            }
            #box .data{
                z-index: 21;
            }
            #box .float{
                float: left;
                width: 40px;
                height: 40px;
                box-shadow: 1px 1px 6px rgba(0,0,0,.6);
            }

            #box .kuang .show{
                opacity: 0;
                position: absolute;
                left: 0;
                top: 0;
                width: 40px;
                height: 40px;
                border-radius: 100%;
                background-color: pink;
                opacity: 0.3;
            }
            #box .pieces .pieces-coor{
                position: absolute;
                left: 0;
                top: 0;
                width: 30px;
                height: 30px;
                box-shadow: 1px 1px 6px rgba(0,0,0,.6);
                border-radius: 100%;
            }
            #box .movepieces .move{
                opacity: 0;
                position: absolute;
                left: 0;
                top: 0;
                width: 20px;
                height: 20px;
                background-color: ​#750606;
                border-radius: 100%;
            }
            #box .over{
                display: none;
                opacity: 0;
                position: absolute;
                top: 0;
                left: 0;
                bottom: 0;
                right: 0;
                margin: auto;
                width: 150px;
                height: 150px;
                border-radius: 10px;
                background-color: pink;
                z-index: 31;
                box-sizing: border-box;
                padding: 20px;
                transition: 1s;
            }
            #box .over h1{
                width: 100%;
                padding: 8px 0;
                border-radius: 10px;
                background-color: red;
                font-size: 20px;
                text-align: center;
                box-shadow: 1px 1px 6px rgba(0,0,0,.6);
            }
            #box .over p{
                width: 100%;
                margin-top: 30px;
                padding: 8px 0;
                border-radius: 10px;
                background-color: red;
                text-align: center;
                font-size: 15px;
                box-shadow: 1px 1px 6px rgba(0,0,0,.6);
                font-weight: bold;
                cursor: pointer;
            }
        </style>
    </head>
    <body>
        <div id="box">
            <!-- 儲存方塊 -->
            <div class="data"></div>
            <!-- 移動紅點 -->
            <div class="kuang">
                <div class="show"></div>
            </div>
            <!-- 儲存棋子 -->
            <div class="pieces">

            </div>
            <!-- 跟隨滑鼠移動的棋子 -->
            <div class="movepieces">
                <div class="move"></div>
            </div>
            <div class="over">
                <h1>遊戲結束</h1>
                <p>從新開始</p>
            </div>
        </div>
        <script src="js/index.js"></script>
    </body>
</html>

相關文章