欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

五子棋网页版

程序员文章站 2022-07-04 22:12:35
...

基于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();
   }

}


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

相关标签: javascript 算法