五子棋网页版

基于js的五子棋教程

先给出问题,然后一步一步的去解决;

  • 需要的知识:html,css,js基础语法,包括创建对象和继承属性;
  • 需要的知识很少,就是js的创建对象,如果不会就去看一下书吧。
  • 整个js都是基于一个叫xuanran 的对象来操作的,所以请大家一边看教程,一遍对照源码,源码很短一共不到200行

面临的问题

  1. 第一个问题,就是这个棋盘怎么显示;
  2. 棋盘显示后,接下来的问题就是,怎么点一下,在一个特定的点显示出一个圆点。
  3. 上面两个问题解决了,五子棋的面貌就存在了,接下来是,怎么把五子棋的位置用变量描述出来,用于量化和计算。
  4. 这一步的问题是,怎么利用棋子的位置变量,计算某一时刻棋子的输赢。判断输赢
    • 以上:这就是制作五子棋按顺序要面临的四个问题,接下来我会按顺序一步一步的解决这四个问题。所有源码和素材可以找我私发

第一个问题

这个问题是怎么显示一个棋盘,是一个渲染问题,渲染这个词不是什么很高级的词,对于网页来说,我想到两种办法,一个是直接一个棋盘图片,另一个是canvas,canvas是个html标签,它在DOM中的对象有很多画图属性,他是一个块级标签,如果用这个就是直接取坐标绘画,我上学期做的MFC版的五子棋就是这个办法,我这次用的是背景图片,比较简单,直接绘图版的我有用MFC做过一个,我也写了实验报告,想参考的同学可以看一下,我把连接给出来:MFC版五子棋

  • 现在进入正题,用一个图片来显示五子棋’

    ‘就用这个来作为一个棋盘它的css是’’’

    #qipan {
        /*棋盘的大小格式*/
        width: 500px;
        height: 500px;
        background: url(../imgs/board.jpg);
        background-size: cover;
        margin-left: 30%;
        padding-left: 4px;
        padding-top: 4px;
    }
    

这样就画出了一个棋盘;第一步OK

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tIZ3JBXR-1593344020745)(csdn/board.jpg)]

第二个问题

怎么显示棋子呢;和点一下出现一个棋子

  1. 首先先根据图片棋盘的大小,15*15d大小,它的大小是500px,在css中有设置,所以每一个棋子的大小是500px/(15+1)=31;这里加1是为了让两个棋子间有空隙

  2. 下面是创造15*15=225个’

    '标签;每一个标签都代表一个棋子,通过设置css属性让每一个棋子变为一个圆形,下面先给出显示的js代码

    ‘’’

    for (var i = 1; i <= 15 * this.qipannum; i++) { //创建div,这个是1是为了计算行列值方便
        var a = document.createElement("div");
        a.setAttribute("data", i);
        a.className = "qizi";
        document.getElementById('qipan').appendChild(a); //把div放进棋盘div里
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EifpxUYO-1593344020747)(csdn/qizi.png)]

  3. 这样就显示了15*15个棋子,从左到右,从上到下,每一个棋子都有一个id数值序号,这样五子棋就做好了,但是一开始肯定是不显示的,点击一下才会显示,所以它的css属性初始为’’’

    .qizi {
        /*棋子的大小格式*/
        width: 30.5px;
        height: 30.5px;
        margin: 1.2px;
        display: inline-block;
        border-radius: 50%;
        /*初始状态如果不设置背景属性就是空白的,不显示*/
    }
    
    1. 现在这些棋子一开始都不显示,我们为每一个div都添加一个事件处理函数,点击一下就改变一下这个div的css属性,关键代码是:’’’

      var y = _this.location(ev).y,
          x = _this.location(ev).x;
      if (_this.data[y][x].qizicontion == 0) {
          if (_this.role == 0) //白棋
          {
              target.style.background = 'aliceblue'; //让这个棋子的颜色显示出来
              _this.role = 1;
              _this.data[y][x].qizicontion = 1; //表示白色
      
          } else {
              target.style.background = 'black';
              _this.role = 0;
              _this.data[y][x].qizicontion = 2; //表示黑色
          }
      
      1. 上面的代码中有一个location函数,这个函数是取一个div的坐标的函数,它的代码是’’’

        xuanran.prototype.location = function(ev) { //给出div的dom对象,判断出这个div的x,y坐标。行列都取决于这个
            var _this = this; //这个必须要设置,在别的函数调用该函数的时候,_this还是指向的对象
            var target = ev.target;
            var data = target.getAttribute('data'); //获取到第N个div
            var y = Math.ceil(data / 15); //表示第y行
            var x = (data % 15); //表示列
            if (x == 0) x = 15;
            return { y: y - 1, x: x - 1 }; //返回一个json,包括div的x,y坐标
        }
        

        现在,棋子问题也解决了OK,会出现下面这个效果

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9pzyu9mJ-1593344020749)(csdn/qizi2.png)]

第三个问题

  1. 上面的location函数,可以获取到每一个div棋子的x,y行竖直坐标,那为何我们不设置一个二维数组来储存它的属性呢?

    ‘’’

    xuanran.prototype.initshuzu = function() { //初始化数组
        var _this = this;
        for (var i = 0; i < 15; i++) { //每一行y
            _this.data[i] = new Array();
            for (var ii = 0; ii < 15; ii++) { //每一列x
                _this.data[i][ii] = { qizicontion: 0 }
            } //每个元素代表一个棋子,0是没有下棋,1是白棋,2是黑棋
        }
    
    }
    

    这个函数,就是初始化数组函数,它会令这个数组,初始化,每一个数组元素保存的都是一个json状态变量。表示棋子的状态

最后一个问题

  • 判断输赢,就是遍历每一行

怎么在某个方向上判断输赢,上下,左右,正斜,反斜;

  1. 先设置两个变量作为棋子在某一行的连在一起的数量。

  2. 设置两个嵌套的for循环,一个代表列,一个代表行,用于遍历数组

  3. 对一行的遍历,直接用逻辑表达式判断是否有五个状态变量qizicontion是否五个连在一起都一样,如果一样就令响应的白或者黑变量,设置为5

  4. 遍历的算法有很多,我这个和之前的MFC版的也不同,怎么样都行,如果你想不到什么好的办法,就用我这个,细节我在源码的注释中写的很清楚了,不做太多解释了,请看源码

    ‘’’

    xuanran.prototype.panduanshuying = function() { //判断输赢
        var _this = this;
    
        var bai = 1,
            hei = 1; //初始临时变量
    
    
    
        //先竖直判断
    
        for (var i = 0; i < _this.qipannum; i++) { //列
            for (var q = 0; q < _this.qipannum - 4; q++) { //行遍历量,放第二级,减4最后留出五个做判断
                if (_this.data[q][i].qizicontion == 1 && _this.data[q + 1][i].qizicontion == 1 &&
                    _this.data[q + 2][i].qizicontion == 1 && _this.data[q + 3][i].qizicontion == 1 && _this.data[q + 4][i].qizicontion == 1) { //直接判断有没有连续的五个在一起
    
                    bai = 5;
    
                }
                if (_this.data[q][i].qizicontion == 2 && _this.data[q + 1][i].qizicontion == 2 && _this.data[q + 2][i].qizicontion == 2 &&
                    _this.data[q + 3][i].qizicontion == 2 && _this.data[q + 4][i].qizicontion == 2) {
                    hei = 5;
                }
            }
        }
    
        //判断竖直
        for (var i = 0; i < _this.qipannum; i++) { //行遍历量
            for (var q = 0; q < _this.qipannum - 4; q++) { //列
                if (_this.data[i][q].qizicontion == 1 && _this.data[i][q + 1].qizicontion == 1 &&
                    _this.data[i][q + 2].qizicontion == 1 && _this.data[i][q + 3].qizicontion == 1 && _this.data[i][q + 4].qizicontion == 1) { //直接判断有没有连续的五个在一起
    
                    bai = 5;
    
                }
                if (_this.data[i][q].qizicontion == 2 && _this.data[i][q + 1].qizicontion == 2 && _this.data[i][q + 2].qizicontion == 2 &&
                    _this.data[i][q + 3].qizicontion == 2 && _this.data[i][q + 4].qizicontion == 2) {
                    hei = 5;
                }
            }
        }
        //右上斜
        for (var i = 4; i < _this.qipannum; i++) { //起始的行,从上往下,从第4行开始这个斜行才有五个棋子,
            //行是先最大,后小。列是先最小,再最大
            for (var hang = i, lie = 0; hang >= 0 + 4, lie < i - 3; hang--, lie++) {
                if (_this.data[hang][lie].qizicontion == 1 && _this.data[hang - 1][lie + 1].qizicontion == 1 && _this.data[hang - 2][lie + 2].qizicontion == 1 &&
                    _this.data[hang - 3][lie + 3].qizicontion == 1 && _this.data[hang - 4][lie + 4].qizicontion == 1)
                    bai = 5;
                if (_this.data[hang][lie].qizicontion == 2 && _this.data[hang - 1][lie + 1].qizicontion == 2 && _this.data[hang - 2][lie + 2].qizicontion == 2 &&
                    _this.data[hang - 3][lie + 3].qizicontion == 2 && _this.data[hang - 4][lie + 4].qizicontion == 2)
                    hei = 5;
            };
            //上面是上部分,下面是下部分
            for (var hang = i - 4, lie = _this.qipannum - 1; hang < _this.qipannum - 4; hang++, lie--) {
                if (_this.data[hang][lie].qizicontion == 1 && _this.data[hang + 1][lie - 1].qizicontion == 1 && _this.data[hang + 2][lie - 2].qizicontion == 1 &&
                    _this.data[hang + 3][lie - 3].qizicontion == 1 && _this.data[hang + 4][lie - 4].qizicontion == 1)
                    bai = 5;
                if (_this.data[hang][lie].qizicontion == 2 && _this.data[hang + 1][lie - 1].qizicontion == 2 && _this.data[hang + 2][lie - 2].qizicontion == 2 &&
                    _this.data[hang + 3][lie - 3].qizicontion == 2 && _this.data[hang + 4][lie - 4].qizicontion == 2)
                    hei = 5;
    
            }
        }
        //右下斜
        for (var i = 0; i < _this.qipannum - 4; i++) //起始的行
        {
            for (var hang = i, lie = 0; hang < _this.qipannum - 4, lie < 14 - i - 3; hang++, lie++) {
                if (_this.data[hang][lie].qizicontion == 1 && _this.data[hang + 1][lie + 1].qizicontion == 1 && _this.data[hang + 2][lie + 2].qizicontion == 1 &&
                    _this.data[hang + 3][lie + 3].qizicontion == 1 && _this.data[hang + 4][lie + 4].qizicontion == 1)
                    bai = 5;
                if (_this.data[hang][lie].qizicontion == 2 && _this.data[hang + 1][lie + 1].qizicontion == 2 && _this.data[hang + 2][lie + 2].qizicontion == 2 &&
                    _this.data[hang + 3][lie + 3].qizicontion == 2 && _this.data[hang + 4][lie + 4].qizicontion == 2)
                    bai = 5;
            }
            for (var hang = i + 4, lie = _this.qipannum - 1; hang > 3; hang--, lie--) {
                if (_this.data[hang][lie].qizicontion == 1 && _this.data[hang - 1][lie - 1].qizicontion == 1 && _this.data[hang - 2][lie - 2].qizicontion == 1 &&
                    _this.data[hang - 3][lie - 3].qizicontion == 1 && _this.data[hang - 4][lie - 4].qizicontion == 1)
                    bai = 5;
                if (_this.data[hang][lie].qizicontion == 2 && _this.data[hang - 1][lie - 1].qizicontion == 2 && _this.data[hang - 2][lie - 2].qizicontion == 2 &&
                    _this.data[hang - 3][lie - 3].qizicontion == 2 && _this.data[hang - 4][lie - 4].qizicontion == 2)
                    hei = 5;
            }
        }
    
    
    
        // if (_this.data[0][0].qizicontion != 0 && _this.data[1][0].qizicontion != 0) bai = 5;
    
        //后判断
        if (bai == 5) {
            _this.stutus = 1;
            _this.showend();
        }
        if (hei == 5) {
            _this.stutus = 2;
            _this.showend();
        }
    
    }
    

到这里,一个五子棋就算做完了

bai = 5;

   //后判断
   if (bai == 5) {
       _this.stutus = 1;
       _this.showend();
   }
   if (hei == 5) {
       _this.stutus = 2;
       _this.showend();
   }

}


### 到这里,一个五子棋就算做完了

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值