JS:来一盘紧张而又刺激的五子棋

来一盘紧张而又刺激的五子棋:自带注释
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        img {
            border: 0;
        }

        ol,
        ul,
        li {
            list-style: none;
        }

        #frame {
            width: 1000px;
            height: 1000px;
            margin: 100px auto;
            border: 5px solid #333;
            background: #fdda9c;
            position: relative;
            overflow: hidden;
        }

        #Board {
            width: 1050px;
            height: 1050px;
            position: absolute;
            top: -25px;
            left: -25px;
        }

        .cBefore {
            width: 100%;
            height: 100%;
            position: absolute;
            background: rgba(0, 0, 0, 0.2);
            z-index: 10;
        }

        .cButt {
            width: 100px;
            height: 200px;
            position: absolute;
            left: 50%;
            top: 50%;
            margin: -120px 0 0 -90px;
            background: #fff;
            padding: 20px 40px;
        }

        .cButt input {
            width: 100px;
            height: 50px;
            margin: 5px 0;
            border-radius: 5px;
        }

        #Board li {
            width: 50px;
            height: 50px;
            position: relative;
            float: left;
        }

        #Board li::before {
            content: "";
            width: 100%;
            position: absolute;
            border-bottom: 1px solid #333;
            top: 50%;
            left: 0;
        }

        #Board li::after {
            content: "";
            height: 100%;
            position: absolute;
            border-right: 1px solid #333;
            top: 0;
            left: 50%;
        }

        #Board li span {
            display: block;
            width: 46px;
            height: 46px;
            position: absolute;
            background: #000000;
            top: 2px;
            left: 2px;
            border-radius: 50%;
            z-index: 9;
        }

        /* #aaaa {
            width: 500px;
            height: 50px;
        } */
    </style>
</head>
<script>
window.onload = function fnGobang() {

    var oWasp = document.getElementById("frame");

    var oBoard = document.createElement("ul");
    oBoard.id = "Board";
    oWasp.appendChild(oBoard);

    /*每个棋格的尺寸*/
    var gridSize = 50;
    /*计算棋格数量,具体公式为 容器边长/棋格尺寸*/
    var W = oBoard.offsetWidth / gridSize; //行
    var H = oBoard.offsetWidth / gridSize; //列
    /*定义黑白子数组*/
    var arrBlack = [];
    var arrWhite = [];
    /*定义黑白子判定,Pass作为交换空间,排序用*/
    var Pass = 0;
    var noPass = false;
    var S = R = L = 1;

    /*一行一行画棋盘线*/
    for (var i = 0; i < W * H; i++) {
        var cGrid = document.createElement("li");
        oBoard.appendChild(cGrid);
    }
    /*获取下一级的li对象,形成一个数组,方便取值*/
    var oGoard = oBoard.getElementsByTagName("li");

    for (var i = 0; i < oGoard.length; i++) {
        oGoard[i].index = i;
        oGoard[i].onclick = function () {
            /*棋子添加逻辑:如果没有子元素。则添加棋子span;以防止同一坐标添加多个对象*/
            
            if (!this.childNodes[0]) {
                

                /*定义span,表示棋子,默认样式是黑色*/
                var cPieces = document.createElement("span");
                /*判断棋子类型,并添加如棋子数组中,并将数组排序,以便后续判定*/
                /*如果是白子,则将颜色转换呈白色白色*/
                if (noPass) {
                    arrWhite.push(this.index)
                    cPieces.style.background = "#fff"
                    sort(arrWhite, Pass)

                    fnWin(arrWhite, "白棋胜!");

                } else {
                    arrBlack.push(this.index)
                    sort(arrBlack, Pass)
                    fnWin(arrBlack, "黑棋胜!")

                }
                this.appendChild(cPieces);
                
                
                /*排序方法,成立的前提是原本的数组是有序的,且从小到大*/
                function sort(arr, pa) {
                    for (var j = arr.length; j > 0; j--) {
                        if (arr[j] < arr[j - 1]) {
                            pa = arr[j];
                            arr[j] = arr[j - 1];
                            arr[j - 1] = pa;
                        }
                    }
                }
/*胜利判定函数*/
function fnWin(arr, str) {
    if (arr.length >= 5) {
        for (var j = 0; j < arr.length; j++) { //alert(j)
            /*横:共5种情况0xxxx x0xxx xx0xx xxx0x xxxx0   
                由于数组是排序过的,因此,只需做两步,连续4个和判定边界
                所谓边界判定,即上下两行由于下表是连续的,因此需要排除此类5子分别位于上下两行的情况情况 
                边界判定原理为:后四个子出现在新一行第一个不能判定胜利   
            */
            console.log(arr)
            if ((arr[j + 4] - arr[j] == 4) && ( arr[j+1]%W!=0) && ( arr[j+2]%W!=0) && ( arr[j+3]%W!=0)&& ( arr[j+4]%W!=0)){
                
                alertWin(str)
            }
            for (var k = j + 1; k < arr.length; k++) {
                /*纵 情况类似,也只需"连续"+边界
                    此时的连续是隔行连续
                    边界判定原理:数组中存在想减为S*W的元素,其中S为连子数量
                */
                if (arr[k] - arr[j] === S * W) {
                    if (S == 4) {
                        alertWin(str+"纵")
                        S = 1;
                        break;
                    } else {
                        S++
                    }
                }
                /*左斜 情况类似,也只需"连续"+边界
                    此时的连续是隔行连续
                    边界判定原理:数组中存在想减为S*(W-1)的元素
                    其中S为连子数量,每隔一行,下标与正下方的点多差上1
                */
                if (arr[j] % W >= 4) {
                    if (arr[k] - arr[j] === L * (W - 1)) { //左斜

                        if (L == 4) {
                            alertWin(str+"左斜")
                            L = 1;
                            break;
                        } else {
                            L++
                        }
                    }
                }
                /*右斜 情况类似,也只需"连续"+边界
                    此时的连续是隔行连续
                    边界判定原理:数组中存在想减为S*(W+1)的元素,
                    其中S为连子数量,每隔一行,下标与正下方的点多多上1
                */
                if (W-(arr[j] % W) >5-S) { 
                    if (arr[k] - arr[j] === R * (W + 1)) { 
                        if (R == 4) {
                            alertWin(str+"右斜") 
                            R = 1;
                            break;
                        } else {
                            R++
                        }
                    }
                }
            }
            /*判定条件恢复初始化*/
            S = L = R = 1;
        }
    }
}
                /*黑白棋子攻守转换*/
                noPass = !noPass;
            }
        }
    }

    function alertWin(a) { //结束

        var cBefore = document.createElement("div");
        cBefore.className = "cBefore";
        var cButt = document.createElement("div");
        cButt.className = "cButt";

        for (var i = 0; i < 3; i++) { //按钮
            var cButton = document.createElement("input");
            cButton.type = "button"
            cButt.appendChild(cButton)
        }

        var oButt = cButt.getElementsByTagName("input");
        oButt[0].value = a;
        oButt[0].style.cssText = "background:none;border:none;"
        oButt[1].value = "重新开始";
        oButt[2].value = "返回游戏";

        for (var i = 1; i < 3; i++) {
            oButt[i].index = i;
            oButt[i].onclick = function () {
                if (this.index == 2) {
                    cBefore.removeChild(cButt);
                    cBefore.style.background = "rgba(0,0,0,0)"
                } else {
                    frame.removeChild(oBoard);
                    fnGobang()
                }
            }
        }
        cBefore.appendChild(cButt);
        oBoard.appendChild(cBefore);
    }
}
</script>

<body>
    <div id="frame">
        <ul id="Board">
        </ul>
    </div>
    <!-- <div id="aaaa">

    </div> -->
</body>

</html>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

椰子奶糖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值