Canvas学习,用Canvas画五子棋并进行简单判断输赢

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>五子棋</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0">
    <style>
        #myCanvas {
            background-color: oldlace;
            box-shadow: 0 0 5px 0px rgba(0, 0, 0, .8);
            border-radius: 5px;
        }
    </style>
</head>
<body>
<canvas id="myCanvas" width="470" height="470"></canvas>

<div></div>
<button onclick="backChess()">回退</button>
<button onclick="resetChess(100)">恢复棋局</button>
</body>

<script>
    var canvas = document.querySelector('#myCanvas')
    var context = canvas.getContext('2d')

    let stepArr = [],
        gap = 30,
        edgeGap = 25,
        // 记录棋盘上所有标记数字
        boardArr = [],
        // 一个小方格的斜边一半大小,用来判断棋子放置的位置
        chessRadius = Math.sqrt(Math.pow(gap, 2) + Math.pow(gap, 2)) / 2,
        // 棋子的半径大小
        chessSize = 13

    // let stepStorage = window.localStorage.getItem('step')
    // if(stepStorage){
    //     stepArr = JSON.parse(stepStorage)
    // }

    /**
     * 窗口坐标转换为Canvas坐标
     * @param canvas
     * @param x 窗口坐标x
     * @param y 容器坐标y
     * @return {{x: number, y: number}}
     */
    function windowToCanvas(canvas, x, y) {
        var bbox = canvas.getBoundingClientRect()
        return {
            x: (x - bbox.left) * canvas.width / bbox.width,
            y: (y - bbox.top) * canvas.width / bbox.width
        }
    }

    /**
     * 根据数字标记转换成坐标值
     */
    function cor2xy(ij) {
        let arr = ij.split('-')
        return {
            x: arr[0] * gap + edgeGap,
            y: arr[1] * gap + edgeGap
        }
    }

    /**
     * 画棋盘上的线
     */
    function drawLine() {
        context.strokeStyle = '#333'
        context.strokeWidth = 1
        for (let i = 0; i < 15; i++) {
            let x1 = edgeGap + i * gap,
                y1 = edgeGap,
                x2 = x1,
                y2 = edgeGap + gap * 14
            context.moveTo(x1 + 0.5, y1)
            context.lineTo(x2 + 0.5, y2)
        }
        for (let i = 0; i < 15; i++) {
            let x1 = edgeGap,
                y1 = edgeGap + i * gap,
                x2 = edgeGap + gap * 14,
                y2 = y1
            context.moveTo(x1 + 0.5, y1)
            context.lineTo(x2 + 0.5, y2)
        }
        for (let i = 0; i < 15; i++) {
            let x = edgeGap + i * gap
            let lineArr = []
            for (let j = 0; j < 15; j++) {
                let y = edgeGap + j * gap
                boardArr.push(`${i}-${j}`)
            }
        }
        context.stroke()
    }

    /**
     * 画中心点
     */
    function drawCenter() {
        context.beginPath()

        let x = edgeGap + 7 * gap,
            y = edgeGap + 7 * gap

        context.arc(x, y, 5, 0, 2 * Math.PI)
        context.fillStyle = '#333'
        context.fill()
    }

    /**
     * 画棋子
     */
    function drawChess(x, y, color) {
        if (!color) {
            color = 'black'
        }
        context.save()
        context.beginPath()
        context.shadowOffsetX = 0; // 阴影Y轴偏移
        context.shadowOffsetY = 0; // 阴影X轴偏移
        context.shadowBlur = 2; // 模糊尺寸
        context.shadowColor = 'rgba(0, 0, 0, .5)'; // 颜色

        context.fillStyle = color
        console.log(color)
        context.arc(x, y, chessSize, 0, 2 * Math.PI)
        context.fill()
        context.restore()
    }

    /**
     * 在交点处画棋子
     */
    function getNearestPos(pos) {
        for (let i = 0; i < boardArr.length; i++) {
            let ijStr = boardArr[i]
            let bPos = cor2xy(ijStr)
            let distance = Math.sqrt(Math.pow(pos.x - bPos.x, 2) + Math.pow(pos.y - bPos.y, 2))
            if (distance <= chessRadius) {
                if (stepArr.indexOf(ijStr) !== -1) {
                    return;
                }
                return {
                    bPos,
                    ijStr
                }
            }
        }
    }

    function checkAllLink(ijStr, x, y, x2, y2) {
        let ijArr = ijStr.split('-')
        // 判断当前棋子的颜色,单数还是双数
        let index = stepArr.indexOf(ijStr) % 2
        // 四个角度判断棋子颜色是否连成5个
        let linkSize = 1
        for (let i = 1; i <= 4; i++) {
            let newijStr = (parseInt(ijArr[0]) + i * x) + '-' + (parseInt(ijArr[1]) + i * y)
            console.log(newijStr, stepArr.indexOf(newijStr))
            if (stepArr.indexOf(newijStr) % 2 !== index) {
                break;
            }
            linkSize++
        }
        for (let i = 1; i <= 4; i++) {
            let newijStr = (parseInt(ijArr[0]) + i * x2) + '-' + (parseInt(ijArr[1]) + i * y2)
            console.log(newijStr, stepArr.indexOf(newijStr))
            if (stepArr.indexOf(newijStr) % 2 !== index) {
                break;
            }
            linkSize++
        }
        return linkSize
    }

    /**
     * 检查输赢
     */
    function checkWin(ijStr) {

        let size = checkAllLink(ijStr, 0, 1, 0, -1)
        if (size >= 5) {
            return true
        }
        size = checkAllLink(ijStr, 1, 0, -1, 0)
        if (size >= 5) {
            return true
        }
        size = checkAllLink(ijStr, 1, -1, -1, 1)
        if (size >= 5) {
            return true
        }
        size = checkAllLink(ijStr, 1, 1, -1, -1)
        if (size >= 5) {
            return true
        }
        return false
    }

    /**
     *  初始化棋盘
     */
    function drawBoard() {
        context.beginPath()
        context.fillStyle = '#f3c281'
        context.fillRect(0, 0, canvas.width, canvas.height)
        drawLine()
        drawCenter()
    }

    function drawChessCover(pos) {
        drawBoard()
        stepArr.forEach((ijStr, index) => {
            let bPos = cor2xy(ijStr)
            if (index % 2 == 0) {
                drawChess(bPos.x, bPos.y)
            } else {
                drawChess(bPos.x, bPos.y, 'white')
            }
        })
        let drawChessTemp = function(x, y, color) {
            context.save()
            context.beginPath()

            let fillColor = 'rgba(255,255,255,.5)'
            if (color == 'black') {
                fillColor = 'rgba(0,0,0,.5)'
            }

            context.fillStyle = fillColor
            context.arc(x, y, chessSize, 0, 2 * Math.PI)
            context.fill()
            context.strokeStyle = color
            context.stroke()
            context.restore()
        }
        if (stepArr.length % 2 == 0) {
            drawChessTemp(pos.x, pos.y, 'black')
        } else {
            drawChessTemp(pos.x, pos.y, 'white')
        }
    }

    /**
     * 下棋事件
     */
    canvas.addEventListener('click', (e) => {
        let pos = windowToCanvas(canvas, e.clientX, e.clientY)

        let res = getNearestPos(pos)
        if (!res) {
            return
        }
        let {bPos, ijStr} = res
        if (stepArr.length % 2 == 0) {
            drawChess(bPos.x, bPos.y)
        } else {
            drawChess(bPos.x, bPos.y, 'white')
        }
        stepArr.push(ijStr)
        // window.localStorage.setItem('step',JSON.stringify(stepArr))
        console.log(stepArr)
        if (checkWin(ijStr)) {
            setTimeout(() => {
                alert('赢了')
            }, 300)
        }

        drawChessCover(pos)
    })

    canvas.addEventListener('mousemove', (e) => {
        let pos = windowToCanvas(canvas, e.clientX, e.clientY)

        let res = getNearestPos(pos)
        if (!res) {
            return
        }
        let {bPos, ijStr} = res

        drawChessCover(bPos)
    })

    /**
     * 回退一步棋
     */
    function backChess() {
        drawBoard()
        stepArr.pop()
        console.log(stepArr)
        stepArr.forEach((ijStr, index) => {
            let bPos = cor2xy(ijStr)
            if (index % 2 == 0) {
                drawChess(bPos.x, bPos.y)
            } else {
                drawChess(bPos.x, bPos.y, 'white')
            }
        })
    }

    /**
     * 恢复棋局`
     */
    function resetChess(timestamp) {
        // 画棋盘
        drawBoard()

        // 恢复棋盘
        stepArr.forEach((ijStr, index) => {
            let bPos = cor2xy(ijStr)
            setTimeout(() => {
                if (index % 2 == 0) {
                    drawChess(bPos.x, bPos.y)
                } else {
                    drawChess(bPos.x, bPos.y, 'white')
                }
            }, timestamp * index)
        })
    }

    resetChess(100)
</script>
</html>

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值