原生js实现 五子棋

发布时间:2019-04-26 22:00:14发布者:Mr.Zhang阅读(418)

先初始化棋盘

HTML:

<!--棋盘-->
<div class="grid"></div>

CSS:

/*棋盘*/
.grid{
    position: relative;
    width: 762px;
    height: 762px;
    background-image: url('./image/timg.jpg');
    -webkit-background-size: 100% 100%;
    background-size: 100% 100%;
    background-position: center center;
    margin: 100px auto;
}

/*每个棋子落点区域*/
.per-zone{
    position: absolute;
    width: 50px;
    height: 50px;
    padding: 10px;
    background-origin: content-box;
    box-sizing: border-box;
    background-position: center center;
    background-size: 100% 100%;
    background-repeat: no-repeat;
}

JS:// 棋盘

const grid = document.getElementsByClassName('grid')[0]; // 棋盘有15列, 15行
const column = 15 , line = 15; // 装棋子的二维数组
let gridArr = []; // 初始化二维数组
function init() { // 文档碎片用来装棋子优化效率
    const fragment = document.createDocumentFragment(); gridArr = new Array(line); for(let i = 0; i < gridArr.length; i ++) { gridArr[i] = new Array(column); for(let j = 0; j < gridArr[i].length; j ++) { // 创建每个棋子落点区域
fragment.appendChild(createZone(j, i)); } } grid.appendChild(fragment); // 事件委托, 性能优化 grid.addEventListener('click', (e) => { begin(e); }, false) } init(); function createZone(x, y) { // 创建棋子 const div = document.createElement('div'); div.classList.add('per-zone'); div.style.left = x * 50 + 7 + 'px'; div.style.top = y * 50 + 7 + 'px'; // 标记棋子的类型,黑子为1, 白子为2, 初始化为0 div.value = 1; div.style.backgroundImage = `url(${'./image/' + div.value + '.png' })`; return div }

我们先让每个棋子的value都为1,看看效果:

不要犯密集恐惧症哦,

我们用事件委托来绑定事件, 这样事件只需要绑定一次而不用绑定15 * 15次,

很大地提升了效率,

开始写点击事件:

// 计数, 用来判定落黑子还是落白子
let count = 0;

// 黑:value =1 ; 白: value = 2
function begin(target) {
// 判断value为0 才能下子
if (!target.value) {
target.value = count%2 + 1 ;
target.style.backgroundImage = `url(${'./image/' + target.value + '.png' })`;
// 判断是否结束
judgeFinish();
count ++ ;
}
 }

现在我们可以下棋了:

很有成就感是不是,就差最后一步也最是核心的一步

判断横着, 竖着, 斜着 是否有5个以上相同颜色的棋子

function judgeFinish() {
    for (let i = 0; i < gridArr.length; i ++) {
        for(let j = 0; j < gridArr[i].length; j ++) {
            // value 为 0 跳过
            if (gridArr[i][j].value === 0) {
                continue;
            }
            // 判断是否五子连珠
            const result = judgeLine(i, j);
            if (result === 1) {
                alert('黑棋胜利');
                replay();
                return
            } else if (result === 2) {
                alert('白棋胜利');
                replay();
                return
            }
        }
    }
}

// 判断向下, 向右, 向斜上, 向斜下四个方向
function judgeLine(x, y) {
    // 黑1, 白2
    let result1 = 3, result2 = 3, result3 =3, result4 =3;
    for (let i = 0; i < 5; i ++) {
        // 向下
        result1 &= y + i < 14 ? gridArr[x][y + i].value : 0;
        // 向右
        result2 &= x + i < 14 ? gridArr[x + i][y].value : 0;
        // 斜上
        result3 &= (x + i > 14 || y - i < 0) ? 0 : gridArr[x + i][y - i].value;
        // 斜下
        result4 &= (x + i > 14 || y + i > 14) ? 0 : gridArr[x + i][y + i].value;
    }
    // 只要有一个方向不为0 游戏结束
    return result1 | result2 | result3 | result4
}


function replay() {
// 装棋子的二维数组
    gridArr = [];

// 计数, 用来判定落黑子还是落白子
    count = 0;
    grid.innerHTML = '';
    init();
}

核心:  使用& 运算符  来  判断 是否 5 子 的 value 相同    

 1& 1& 1& 1& 1 = 1 

2 & 2 &2 &2 &2  = 2  

为什么初始值设成3 呢, 因为任何数 & 3  都不会变     

先转化成2进制 再运算  3 =》 11   

最后的效果:

 





本文转自博客园,原文地址:https://www.cnblogs.com/LHLVS/p/10775842.html