你所在的位置:首 页 >> 前台技术 >> 详细新闻页面


JavaScript实例 | 使用原生JS写五子棋

作者:zhirong1230 创建时间:2017-07-09 阅读次数:1638


通过制作五子棋实例

掌握作用域、原型、闭包、多态等

前端基础知识点的应用

前端开发者们

一起来看看吧





前言

听说这是一道腾讯的面试题,可能网上已经有不少答案了,晚上没事看到这道题就自己做了下。逻辑很简单,考虑到是面试题,使用了 ES6 的语法。本文介绍下核心逻辑跟部分代码。

目录

  1. 前言

  2. 目录

  3. 思路

  4. 保存已下的棋

  5. 判断落子后是否胜利

  6. 对外 API 与 UI 绑定

  7. 结语

思路

核心逻辑大致如下:

保存已下的棋

我们建立个对象保存已下的棋,该对象的结构形为{x6y9: 1, x3y8: 2, x20y1: 2 ...},初始为空,每次落子都给它添加属性,属性名表示坐标,属性值表示棋子颜色,1为白色,2为黑色,未配置的属性查询返回0。同时设两个方法用来操作该对象。

var board = new Proxy({},{         get: function(target, property) {        
        if (property in target) {            return target[property];
        } else {            
            return 0        }
    }
}) //--------// getProps(x,y) {    
    return 'x'+x+'y'+y
}
getColor(board, x, y) {    
    return board[this.getProps(x,y)]
}

判断落子后是否胜利

首先获取 4 条轴上的坐标,我们设落子点的坐标为[x, y],那该点左上角的左边为 [x – 1, y – 1],右下角为 [x +1, y +1],所以每个方向都是 x,y 与 1, -1, 0 三个数两两形成的数组加 4 次。如我们设落点坐标为[0,0],则左上角的4个位置就是:

var var lt = [] for(var i = 1;i<5;i++) {
    lt.push([0-i, 0-i])
}
console.log(lt)     // [[-1,-1], [-2, -2], [-3, -3], [-4, -4]]

可以看出8个方向的相加值分别为[-1,-1], [-1,0], [1, -1], [-1, 0],以及它们的相反值。

var roundDirect = [[-1,-1], [-1,0], [1, -1], [-1, 0]]

接下来写个函数checkRoundDirect用来判断是否胜利,接收roundDirect数组作为参数:

// 判断 4 个轴中是否有一个成立 checkRoundDirect(x, y, board, roundDirect) {    
    return roundDirect.some(direct => this.checkSingleDirect(x, y, board, direct))
}

这里把每条轴的判断交给checkSingleDirect函数判断:

// 判断单个轴(两个方向)是否成立 checkSingleDirect(x, y, board, direct) {         var leftDirect = direct         var rightDirect = direct.map(v=>-v)         var getNum = this.getDirectSameColorNum.bind(this, x, y, board)
    return (getNum(leftDirect) + 1 + getNum(rightDirect)) >= 5  
}

判断单轴是否成立的逻辑是以落子为起点,它左侧与右侧的连续相同颜色的点棋子数目相加大于 4,再加上落子本身,就是形成了 5 子。

中心点与一侧的连续相同颜色棋子的数量通过getDirectSameColorNum函数获取:

// 返回每个方向的颜色值相同的棋子数 getDirectSameColorNum(x, y, board, direct) {    
    var result = 0    var bindGetcolor = this.getColor.bind(this, board)    
    var activeColor = bindGetcolor(x,y)    

    for (var i = 1; i < 5; i++) {        
        var nextColor = bindGetcolor(x + i * direct[0], y + i * direct[1])        
        if (activeColor == nextColor) { result++ } else {break}
    }    
    return result
}

这样通过调用checkRoundDirect函数并传入当前点的x, y参数以及已知的board, roundDirect参数,就可以得到落子后是否胜利连成 5 子。

对外 API 与 UI 绑定

每个棋盘实例对外输出以下属性与接口。

属性:

接口:

同时构建一个棋盘的 UI 对象并返回一个配置函数用来初始化棋盘实例,这里我就不写 UI 对象的具体实现了,各位有兴趣的可以查看源码,UI 对象的主要目的是绑定棋盘实例、渲染页面、绑定事件。

棋盘 UI 对象主要接收以下参数:

棋盘实例与 UI 绑定后共同输出一个函数用来初始化棋盘,按如下方式调用:

// 初始化游戏,(棋盘大小,{结束事件,落子事件}) Game.start(15,{
    onEnd(color) {
        alert(`游戏结束, ${color === 1 ? '白子' : '黑子'}胜利`)
    },
    onKeep(color) {
        document.getElementById('info').innerHTML = `${color !== 1 ? '白子' : '黑子'}回合`
    }
})

结语

这个五子棋很简单,只要有基本的 js 基础跟清晰的思路就能很快做出来。源码中涉及到了作用域、原型、闭包、多态、柯里化等基础知识,以及对对象、函数、数组等方法的运用,同时使用了 ES6 的语法。



    关键词(keywords):JavaScript实例 | 使用原生JS写五子棋

分享到: 更多


前一篇: Java编程的10大学习路线            后一篇:传说中Python最难理解的点,看这完篇就够了

phpchina   php爱好者   php100    中国网管联盟   LAMP兄弟连   河北联合大学   胜芳趣团网   rss 联系我们 问题反馈
版权所有@:ABCMS新闻发布系统!
建议使用ie6、ie8和 ff 浏览器进行浏览 | 建议分辨率:1024x768
地址:唐山市路北区高新技术产业园区龙华道128号 | 邮编:63000| 邮箱:zhirong1230@yeah.net