网页版五子棋
学习了HTML5新标签画布,觉得以前想做五子棋练手的想法有了技术支持,随即实现了一下,仅保证功能,页面样式尚没有设计。
*注意:本代码尚未考虑浏览器兼容性
*注意:设置尺寸时不要超出屏幕范围,使产生滚动条(我做的基础版,尚未考虑scroll距离)
- 关于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 = {} //白棋的棋子对象
- 我们首先绘制棋盘
这里我定义了宽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文件代码
到此,棋盘绘制完毕,
- 为棋盘添加点击监听事件
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)作为画棋子的坐标
- 关于画图函数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
}
- 判断五子连珠
最核心的函数,在每一次画完棋子之后都要进行判断
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,四个方向进行五子判断
- 重新开始
这是一个刷新函数
document.getElementById("re").onclick = function () {
location.reload()
}
- 运行结果
展示结果样式也没有做,大家有需要可以加模态框
代码供参考,请大家多多提出改进意见