随便写了个五子棋,只能左右手互博,没写电脑

14,242 阅读3分钟

第一次写掘金帖子,没啥经验,也是写来玩玩的

闲来没事,写了个五子棋玩玩,基于canvas写的,大概长这样:↓↓↓↓

1663899137624.jpg

首先是css的代码

*{
    padding: 0;
    margin: 0;
}
body,html{
    width: 100%;
    height: 100%;
    position: relative;
    background-color: #eee;
}
.wrap{
    width: 700px;
    height: 700px;
    position: absolute;
    top: calc(50% - 40px);
    left: 50%;
    transform: translate(-50%, -50%);
}
.control_wrap{
    width: 100%;
    position: absolute;
    bottom: 10%;
    left: 50%;
    transform: translateX(-50%);
    text-align: center;
    font-size: 16px;
    color: #333;
}

.control_wrap span{
    margin-right: 4px;
}

.control_wrap input{
    border: none;
    padding: 10px;
    font-size: 16px;
    border-radius: 6px;
}

.control_wrap button{
    width: 90px;
    height: 30px;
    margin-left: 10px;
    cursor: pointer;
}

然后是简单的html布局

这部分主要就是一个canvas,然后加了个控制栏,控制栏里面联上了js里的几个数据

<div class="wrap">
    <canvas id="canvas" width="800" height="800"></canvas>
</div>
<div class="control_wrap">
    <span>棋盘大小:</span>
    <input type="text" class="stage_big" value="700">
    <span>连子获胜:</span>
    <input type="text" class="win_num" value="5">
    <button class="start_btn">开始游戏</button>
</div>

最后是js的部分了,这部分代码我写得比较多,没有优化过的,主要懒的

首先是基础数据,简单地写了点注释

let arr = []; //数据矩阵
let stageLeng = 25; //数组长度
let stageWidth = 700; //初始化棋盘大小
let _w = stageWidth/stageLeng | 0; //棋盘线条间隔
let gameState = 'finish'; //游戏状态 start finish 两个状态
let linNumber = 5; //胜利需要连几颗棋子
let black = document.createElement('img'); //棋子图片
let white = document.createElement('img'); //白色棋子图片
black.src = './black.png';
white.src = './white.png';
let c_width = _w * 0.8 | 0; //棋子的宽高
c_width = c_width % 2 ? c_width + 1 : c_width;
let canvas = document.querySelector('#canvas');
canvas.width = stageWidth; //画布的宽度
canvas.height = stageWidth; //画布的高度
let ctx = canvas.getContext('2d');
let isBlack = true; //是否轮到黑棋,每轮变换

然后开始游戏按钮,拿到控制的数据,或者默认数据

document.querySelector('.start_btn').onclick = function (){
    // if(gameState == 'start') return false;

    let stageBig = document.querySelector('.stage_big').value || 700;
    let winNum = document.querySelector('.win_num').value || 5;
    if(stageBig != stageWidth){
            document.querySelector('.wrap').style.width = stageBig + 'px';
            document.querySelector('.wrap').style.height = stageBig + 'px';
            stageWidth = stageBig | 0;

            _w = stageWidth/stageLeng | 0;

            c_width = _w * 0.8 | 0;
            c_width = c_width % 2 ? c_width + 1 : c_width;

            canvas.width = stageWidth; //画布的宽度
            canvas.height = stageWidth; //画布的高度
    }

    linNumber = winNum != linNumber ? winNum | 0 : linNumber;

    initList();
    drawCheckerboard();
    gameState = 'start';
};

初始化棋盘

function initList (){
    arr = [];
    for(let i = 0; i < stageLeng; i++){
            let aaa = []
            for(let b = 0; b < stageLeng; b++){
                    aaa.push(0)
            }
            arr.push(aaa)
    }
}

在canvas上画棋盘的线

function drawCheckerboard(){ //绘画棋盘的线条
    ctx.fillStyle="#caa281";
    ctx.fillRect(0,0,stageWidth,stageWidth);

    let _p = new Array(stageLeng).fill([0, 0]);

    for(let i = 0; i < stageLeng; i++){
            ctx.lineWidth="1";
            ctx.strokeStyle = '#000'
            ctx.beginPath();
            ctx.moveTo(0, i*_w);
            ctx.lineTo(stageWidth, i*_w);
            ctx.stroke();
            _p[i][1] = i * _w;
    }

    for(let i = 0; i < stageLeng; i++){
            ctx.lineWidth="1";
            ctx.strokeStyle = '#000'
            ctx.beginPath();
            ctx.moveTo(i*_w, 0);
            ctx.lineTo(i*_w, stageWidth);
            ctx.stroke();
            _p[i][0] = i * _w;
    }

}

在棋盘上增加点击事件这里用的是canvas代理

canvas.onclick = function(e){ //给棋盘增加点击事件
    if(gameState == 'finish') return false;
    let x = e.clientX - this.getBoundingClientRect().left | 0;
    let y = e.clientY - this.getBoundingClientRect().top | 0;

    drawChess(x, y)
}

跟点击事件配合的就是在棋盘上绘制棋子

function drawChess(x, y){ //在棋盘上绘制棋子
    let _x = x % _w;
    let _y = y % _w;

    _x > (_w / 2 | 0) ? x += parseInt(_w - _x) : x -= _x;
    _y > (_w / 2 | 0) ? y += parseInt(_w - _y) : y -= _y;

    let l = x / _w | 0, j = y / _w | 0;
    if(arr[j][l] || l == 0 || j == 0 || l == arr.length || j == arr.length) return false;
    arr[j][l] = isBlack ? 1 : 2;

    ctx.drawImage(isBlack ? black : white, x - (c_width / 2), y - (c_width / 2), c_width, c_width);
    checkWin(isBlack ? 1 : 2);
    isBlack = !isBlack;
}

最后就是判断输赢,说实话,这个我看别人的写的好简单,然后我用了个最慢的方法,就是去盘一个米字,看看当前有没有连着N个棋子,是否达到了胜负条件

function checkWin(target){
    let end = getCondition(target);
    //横的 + 竖的
    for(let i = 0; i < arr.length; i++){
            let linkString = "";
            for(let j = 0; j < arr.length; j++){
                    linkString+=arr[j][i];
                    if(arr[i].join("").includes(end) || linkString.includes(end)){
                            alert('游戏结束'+(target == 1 ? ',黑棋' : ',白棋')+'获胜');
                            console.info('结束',target == 1 ? '黑棋' : '白棋', '赢了');
                            gameState = 'finish'
                            return false;
                    }
            }					
    }

    checkSlashWin(target, end);
    reverseSlashWin(target, end);
};

function getCondition(t){
    let e = ''
    for(let i = 0; i< linNumber; i++){
            e += t;
    }

    return parseInt(e)
};

function checkSlashWin(target, end){				
    let _idx = arr.length - 1;
    let flag = true
    while(_idx > linNumber - 1){
        let linkString = "";
        let i = arr.length - 1, j = _idx;
        while(j > 0){
            if(flag) {linkString += arr[i][j];}
                    else {linkString += arr[j][i];}
            i--;
            j--;
        }
        _idx--;

            if(_idx == linNumber - 1 && flag){
                    flag = false;
                    _idx = arr.length - 1;
            }

            if(linkString.includes(end)){
                    alert('游戏结束'+(target == 1 ? ',黑棋' : ',白棋')+'获胜');
                    console.info('结束',target == 1 ? '黑棋' : '白棋', '赢了');
                    gameState = 'finish'
                    return false;
            }
    }
}

function reverseSlashWin(target, end){
    let idx = arr.length -1;
    let flag = true;
    while(idx > 0){
        let linkString = "";
        let i = arr.length - 1, j = idx;
            if(flag){
                    i = 0;
                    while(j > 0){
                            linkString += arr[i][j];
                            i++;
                            j--;
                    }
            }else {
                    while(j < arr.length){
                            linkString += arr[i][j];
                            i--;
                            j++;
                    }
            }
            idx--;
            if(idx == 0 && flag){
                    flag = false;
                    idx = arr.length -1
            }
            if(linkString.includes(end)){
                    alert('游戏结束'+(target == 1 ? ',黑棋' : ',白棋')+'获胜');
                    console.info('结束',target == 1 ? '黑棋' : '白棋', '赢了');
                    gameState = 'finish'
                    return false;
            }
    }

}

基本就这样,第一次写帖子,第一次用canvas写东西,没啥经验,见谅见谅

两张棋子的图片

black.png

white.png

下面是全部的代码--不过缺两张棋子的图