基于HTML5<canvas>的五子棋

网页版五子棋

学习了HTML5新标签画布,觉得以前想做五子棋练手的想法有了技术支持,随即实现了一下,仅保证功能,页面样式尚没有设计。

*注意:本代码尚未考虑浏览器兼容性
*注意:设置尺寸时不要超出屏幕范围,使产生滚动条(我做的基础版,尚未考虑scroll距离)

  1. 关于js全局变量
    放在js文件最前面
let wzq = document.getElementById("wzq")
let context = wzq.getContext("2d") //务必不要省略
let cilckX = -1
let clickY = -1
let user = true  //true为此时黑方落子
let chessPictB = {}  //黑棋的棋子对象
let chessPictW = {}   //白棋的棋子对象
  1. 我们首先绘制棋盘
    这里我定义了宽1000px,高600px。一个格子的宽高为50px
body {
        margin: 0;
    }

#wzq {
        margin-top: 10px;
        margin-left: 10px;
        background-color: #CCCC66;
    }

这是一些样式

<canvas id="wzq" width="1000" height="600"></canvas>
<div id="res"></div>
<button id="re">重新开始</button>

html文件代码

for (let x = 0.5; x < 1000; x += 50) {
        context.moveTo(x, 0)
        context.lineTo(x, 600)
    }
    for (let y = 0.5; y < 600; y += 50) {
        context.moveTo(0, y)
        context.lineTo(1000, y)
    }
    context.strokeStyle = "#000"
    context.stroke()

js文件代码
到此,棋盘绘制完毕,
棋盘

  1. 为棋盘添加点击监听事件
wzq.addEventListener("click", clickFunction, false)

function clickFunction(e) {
        cilckX = e.clientX - 10 //我的wzq有10px的margin-top和margin-left
        clickY = e.clientY - 10
        let xY = resXy(cilckX, clickY)
        if (!draw(xY["0"], xY["1"])) {
            alert("请不要覆盖棋子")
            return
        }
        let win = judge(xY["0"], xY["1"])
        if (win) {
            document.getElementById("res").innerHTML = user ? "黑棋胜" : "白棋胜"
            wzq.removeEventListener('click', clickFunction) //宣布之后应该为画布解绑监听事件
        }
        user = !user
    }

当获取到鼠标点击位置( e.clientX, e.clientY)时,我们需要小小的处理一下,使这个坐标转变为画布上离点击点最近的交叉点的坐标。
在这里,转换函数为

function resXy(x, y) {
        let resXy = {}
        for (let a in arguments) {
            let res = arguments[a] / 50
            let floor = Math.floor(res)
            let ceil = Math.ceil(res)
            Math.abs(floor * 50 - arguments[a]) > Math.abs(ceil * 50 - arguments[a]) ? resXy[a] = ceil * 50 : resXy[a] = floor * 50
        }
        return resXy //返回值为对象{0:x值,1:y值}
    }

通过将上下取整,得到点击点周围四个交叉点的坐标,其中最近的即为绘制棋子的位置。
例如:点击点为(93,195),通过x,y除以50的商上下取整之后再乘以50,我们得到(50,150)(50,200)(100,150)(100,200),选择离点击点最近的(100,200)作为画棋子的坐标

  1. 关于画图函数draw
function draw(x, y) {
        if (chessPictB["xy" + x + y] != undefined || chessPictW["xy" + x + y] != undefined) {
            return false
        } // 得保证点击的交叉点没有棋子
        context.beginPath();
        context.arc(x, y, 15, 0, 2 * Math.PI) //画圆
        context.fillStyle = user ? "#000" : "#FFFFFF"
        context.fill()
        context.closePath()
        user ? chessPictB["xy" + x + y] = true : chessPictW["xy" + x + y] = true
        return true
    }
  1. 判断五子连珠
    最核心的函数,在每一次画完棋子之后都要进行判断
function judge(x, y) {
        let num = 0
        let chessPict = user ? chessPictB : chessPictW
        let newX = x - 50
        let addLost = true
        //水平方向
        while (num != 5) {
            if (chessPict["xy" + newX + y] != undefined) {
                num++
                addLost ? newX -= 50 : newX += 50
            }
            else {
                newX = x
                if (addLost)
                    addLost = false
                else
                    break
            }
        }
        if (num == 5) return true
        //垂直方向
        let newY = y - 50
        num = 0
        addLost = true
        while (num != 5) {
            if (chessPict["xy" + x + newY] != undefined) {
                num++
                addLost ? newY -= 50 : newY += 50
            }
            else {
                newY = y
                if (addLost)
                    addLost = false
                else
                    break
            }
        }
        if (num == 5) return true
        //斜方向,左下右上
        newX = x - 50
        newY = y + 50
        num = 0
        addLost = true
        while (num != 5) {
            if (chessPict["xy" + newX + newY] != undefined) {
                num++
                if (addLost) {
                    newY += 50
                    newX -= 50
                }
                else {
                    newY -= 50
                    newX += 50
                }
            }
            else {
                newY = y
                newX = x
                if (addLost)
                    addLost = false
                else
                    break
            }
        }
        if (num == 5) return true
        //斜方向,左上右下
        newX = x - 50
        newY = y - 50
        num = 0
        addLost = true
        while (num != 5) {
            if (chessPict["xy" + newX + newY] != undefined) {
                num++
                if (addLost) {
                    newY -= 50
                    newX -= 50
                }
                else {
                    newY += 50
                    newX += 50
                }
            }
            else {
                newY = y
                newX = x
                if (addLost)
                    addLost = false
                else
                    break
            }
        }
        if (num == 5) return true
    }

我分了水平方向,竖直方向,斜率为1,斜率为-1,四个方向进行五子判断

  1. 重新开始
    这是一个刷新函数
document.getElementById("re").onclick = function () {
        location.reload()
    }
  1. 运行结果
    运行结果
    展示结果样式也没有做,大家有需要可以加模态框

代码供参考,请大家多多提出改进意见

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值