美文网首页
JS实现五子棋——UI篇

JS实现五子棋——UI篇

作者: allen151 | 来源:发表于2017-08-03 21:41 被阅读2651次

    介绍内容

    前些时间,阿尔法狗对战柯洁围棋大赛很热门,那只是人工智能中的一个方向,展示了机器能代替人做某些事情。
    而围棋是很讲究智力的游戏,所以实现起来也是很难的,Google花了很多钱这在方面。
    那段时间我也用JS写了一个小游戏——五子棋,五子棋相对来讲简单很多。我那时候在公众号上展示给大家,好像大家兴趣不大,可能是因为五子棋游戏太过简单,又或者是对我推的东西不感兴趣。那个公众号已经被封杀了,现在我又重新开了一个公众号。下面有二维码,如果有兴趣可以推一下。
    现在我要写一下教程,你们可以点击这里体验一番。
    这个实例完全是用JS实现的,有UI部分也有AI部分,我们需要有一定的canvas和JS的知识就足够了。

    • 棋盘的实现
      1.canvas绘画直线。
      2.设置画笔的颜色。

    • 棋子的实现
      1.canvas画圆。
      2.填充渐变色。

    页面结构

    页面上有一个正方形的棋盘,我们用画布canvas来实现棋盘。

    <canvas id="chess" width="450px" height="450px"></canvas>
    

    棋盘有一定的阴影效果,使棋盘更美观些。我们通过定义CSS样式来实现。

    canvas {
        display: block;
        margin: 50px auto;
        box-shadow: -2px -2px 2px #EFEFEF, 5px 5px 5px #B9B9B9;
    }
    

    这个时候的效果如下,有一定的阴影效果:

    阴影效果

    画棋盘的网格

    这里用到JS来控制canvas画棋盘,我们知道五子棋的棋盘是由些纵线和横线组成的,棋盘的样子如下:

    网格的实现

    分别有15条纵线和横线,每个格子为30px的正方形,棋盘边缘有15px的补白。

    在棋盘中实现画线

    在JS中用画笔画一条线:

    var chess = document.getElementById("chess") ;//获取canvas
    var context = chess.getContext("2d");
    context.strokeStyle = "#aaa" ;//画笔的颜色
    context.moveTo(15,15);
    context.lineTo(435,15);
    context.stroke();
    

    效果:

    一条横线的画法

    开始画棋盘的网线

    我们回顾了一下画线,那接下来我们用循环方式画15条纵线和15条横线:

    var chess = document.getElementById("chess") ;//获取canvas
    var context = chess.getContext("2d");
    
    context.strokeStyle = "#aaa" ;//画笔的颜色
    
    for (var i=0; i<15; i++) {//通过循环画网格
        context.moveTo(15,15+i*30);
        context.lineTo(435,15+i*30);
        context.stroke();
        context.moveTo(15+i*30,15);
        context.lineTo(15+i*30,435);
        context.stroke();
    }
    
    

    效果:

    完成网格

    棋盘背景

    可能你已经发现了,白色的棋盘背景视觉非常不好,那么接下来我们就来为棋盘添加背景。我们选择一张木色的图片,如果你想为棋盘添加你特有的水印,可以通过制图软件添加。
    H5添加图片的方法是通过画图的方式,画上去就会覆盖掉之前画的网格,所以我们通过对画网格的代码进行封装成一个函数,画完背景后再调用画网格的函数来达到不被覆盖的效果。总的代码如下:

    var img = new Image();
    img.src = "img/2.png" ; 
    img.onload = function (){
        context.drawImage(img,0,0,450,450);
        drawLine();
    }
    function drawLine () {//把画线封装成函数
        for (var i=0; i<15; i++) {//通过循环画网格
            context.moveTo(15,15+i*30);
            context.lineTo(435,15+i*30);
            context.stroke();
            context.moveTo(15+i*30,15);
            context.lineTo(15+i*30,435);
            context.stroke();
        }
    }
    

    最终的效果:

    棋盘效果

    画棋子

    我们是在背景上画棋子的,所以画棋子的代码应该放在onload方法里面。

    棋子的画法

        context.beginPath() ;
        context.arc(200,200,100,0,2*Math.PI);
        context.closePath() ;
        context.fill();
    

    解释一下特别的代码context.arc(200,200,100,0,2*Math.PI);四个参数分别是圆心横坐标、圆心纵坐标、半径、开始弧度、结束弧度。
    context.fill();给圆填充颜色。
    效果:

    一个棋子
    这个效果还不像棋子,棋子中间要有些发亮才行的,我们给棋子中间加一个亮度的渐变:
    我们直接看onload方法里的代码,再解释其中重要的代码:
    img.onload = function (){
        context.drawImage(img,0,0,450,450);
        drawLine();
        //画棋子  
        context.beginPath() ;
        context.arc(200,200,100,0,2*Math.PI);
        context.closePath() ;
        var gradient = context.createRadialGradient(200, 200, 50, 200, 200, 20);
        gradient.addColorStop(0, "#0a0a0a");
        gradient.addColorStop(1, "#636766");
        context.fillStyle = gradient ;
        context.fill();
    }
    

    这些代码的操作非常简单,首先画一个圆,然后填充渐变色,var gradient = context.createRadialGradient(200, 200, 50, 200, 200, 20);这是定义一个有渐变的颜色变量,前三个参数是圆心在(200,200)处,半径为50的一个圆,同理,后三个参数是圆心在(200,200)处,半径为20的一个圆。

    gradient.addColorStop(0, "#0a0a0a");
    gradient.addColorStop(1, "#636766");
    context.fillStyle = gradient ;
    

    这三行代码分别设置上面的第一个圆的颜色,第二个圆的颜色,和把渐变色填充给棋子。最终的填充效果是在圆心为(200,200)内径为20,外径为50的一个圆环上产生渐变。
    棋子最后的效果:

    中间发亮

    落子样式

    那我们通过上面的学习就会画一个棋子啦,接下来我们改变棋子的半径大小和颜色就能得到我们想要的棋子了。
    代码放在onload里面会显得很杂乱,这是我们不想看到的,所以我们必须封装成函数再使用。
    封装成以下的函数:

    var oneStep = function (i, j, me){//i,j分别是在棋盘中的定位,me代表白棋还是黑棋
        context.beginPath() ;
        context.arc(15+i*30, 15+j*30, 13, 0, 2*Math.PI);//圆心会变的,半径改为13
        context.closePath() ;
        var gradient = context.createRadialGradient(15+i*30+2, 15+j*30-2, 15, 15+i*30, 15+j*30, 0);
        if(me){
            gradient.addColorStop(0, "#0a0a0a");
            gradient.addColorStop(1, "#636766");
        }else{
            gradient.addColorStop(0, "#D1D1D1");
            gradient.addColorStop(1, "#F9F9F9");
        }
        context.fillStyle = gradient ;
        context.fill();
    }
    

    主要改变了三部分,改变圆心和半径,根据接收到的参数确定圆心,判断是黑子还是白子。
    然后通过在onload方法里调用函数来落子:

    oneStep(0,0,true) ;
    oneStep(1,1,false) ;
    

    效果:

    改变棋子大小

    实现鼠标落子

    实现用鼠标点击棋盘就落下一颗棋子,我们用在画布上绑定单击事件来实现,代码如下:

    var me = true ;
    chess.onclick = function (e){
        var x = e.offsetX ;
        var y = e.offsetY ;
        var i = Math.floor(x/30) ;
        var j = Math.floor(y/30) ;
        oneStep(i,j,me);
        me = !me ;
    }
    

    通过e.offsetXe.offsetY两个属性得到坐标,后转化成i和j,再调用oneStep()方法,定义一个变量me来决定是黑子还是白子,每点击一次就改变一次me的值。
    效果:

    鼠标落子
    vzsf
    这时候还有一个问题,已经下了黑子的点,重新点击还会被白子覆盖掉。那怎么解决呢?
    首先我们定义一个二维数组,存放所有的落子点,如果有落子,就给其记录下来。落子的时候再判断是否已经落子,如果已经落子了就不允许重新落子。思路就是这样。
    二维数组代码:
    var chessBoard = [] ;
    for (var i=0; i<15; i++) {
        chessBoard[i] = [] ;
        for (var j=0; j<15; j++) {
            chessBoard[i][j] = 0;
        }
    }
    

    二维数组的初始值都是0,然后在单击事件的方法里添加一个判断:

    chess.onclick = function (e){
        var x = e.offsetX ;
        var y = e.offsetY ;
        var i = Math.floor(x/30) ;
        var j = Math.floor(y/30) ;
        if(chessBoard[i][j] == 0){
            oneStep(i,j,me);
            if(me){
                chessBoard[i][j] = 1 ;
            }else{
                chessBoard[i][j] = 2 ;
            }
            me = !me ;  
        }
    }
    

    落子位置等于0才可以落子,落完子后给相应的点附非0值,黑子就附1,白子附2。
    效果:

    落子不能覆盖

    总结

    这是UI篇,你继续翻翻我的主页,肯定能找到AI篇的。

    • 棋盘的实现
      通过循环画直线

    • 棋子的实现
      画出你想要的棋子,渐变填充颜色,封装成一个函数供调用。

    • 落子的实现
      用数组存放每一个落子点,满足条件就落下对应的子。

    UI篇到此就告一段落了,这里用到的知识并不多,相应的方法想了解更多可以到W3上看。AI篇将会在后期推出,到时候就可以实现人机交互了。跟自己打的代码比试五子棋不再只是一种想法,只要你动手,一定能实现。另外,想跟我的代码比试一下可以点击这里

    相关文章

      网友评论

          本文标题:JS实现五子棋——UI篇

          本文链接:https://www.haomeiwen.com/subject/plrmlxtx.html